千家信息网

java JPA中的EntityManager是怎样的

发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,java JPA中的EntityManager是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。JPA即Java Persist
千家信息网最后更新 2025年12月02日java JPA中的EntityManager是怎样的

java JPA中的EntityManager是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

JPA即Java Persistence API,是Java EE中针对持久化数据提供的规范。在使用JPA中,我们经常会提到Entity,Entity就是在内存中短暂存活,在数据库中被持久化了的对象。Entity和数据库中的表映射,也就是我们常说的ORM。我们可以持久化一个Entity,删除一个Entity或者通过Java Persistence Query Language(JPQL)来查询Entity。

通过注解的方式声明一个entity如下:

Java代码

  1. @Entity

  2. public class Book {

  3. @Id

  4. @GeneratedValue

  5. private Long id;

  6. private String title;

  7. private Float price;

  8. private String description;

  9. private String isbn;

  10. private Integer nbOfPage;

  11. private Boolean illustrations;

  12. // Getters, setters

  13. }



Book Entity和数据库的映射关系如图:



在JPA中,所有的Entity都是通过javax.persistence.EntityManager的API来管理和操纵的。当EntityManager管理Entity时,所有的Entity都会有一个唯一标识(这个标识通常是主键列),Entity的状态将会和数据库同步。当Entity脱离EntityManager的管理时,Entity就变成了一个普通的Java对象实例,这时它的状态是detached。
当我们用new关键字创建一个新Entity时,这个Entity对象存在于内存中,JPA对它没有任何了解。只有当EntityManager开始管理它时,它的状态才会和数据库同步。当调用了EntityManager.remove方法后,它就会从数据库中删除掉,但Java对象还会在内存中存在,直到被垃圾回收掉。



在我们介绍EntityManager API之前,我们先来看看Persistence Context的概念。一个Persistence Context就是针对一个事物中一段时间内一群被管理的Entity的集合。多个具有相同唯一标识的Entity实例不能存在于同一个Persistence Context中。例如,一个Book实例的ID是12,此时就不能有第二个ID也是12的Book实例存在于相同的Persistence Context中了。只有存在于Persistence Context中的Enitity才会被EntityManager所管理,它们的状态才会反映到数据库中。Persistence Context可以被看成一个一级缓存,它可以被EntityManager当作存放Entity的缓存空间。默认情况下,Entity在Persistence Context存活,直到用户的事物结束。

每个事物用户都有自己的Persistence Context,多个Persistence Context访问同一个数据库的实例如下图:



我们可以调用EntityManager.persist()方法来持久化一个Entity,也就是向数据库中插入数据。

Java代码

  1. Customer customer = new Customer("Antony", "Balla", "tballa@mail.com");

  2. Address address = new Address("Ritherdon Rd", "London", "8QE", "UK");

  3. customer.setAddress(address);

  4. tx.begin();

  5. em.persist(customer);

  6. em.persist(address);

  7. tx.commit();



上例中的Customer和Address是两个普通的Java对象,当被EntityManager调用了persist方法后,两个对象都变成了EntityManager所管理的Entity。当Transaction提交后,他们的数据会被插入到数据库中。这里的Customer对象是对象关系的持有者,它对应的表结构应当有一个外键来对应Address对象。
我们注意一下存储两个对象的顺序。即便是将两个对象存储的顺序颠倒一下,也不会造成外键找不到的错误。之前我们已经说过了,Persistence Context可以被看作一级缓存。在事物被提交之前,所有的数据都是在内存中的,没有对数据库的访问,EntityManager缓存了数据,当数据准备好后,以底层数据库期待的顺序将数据更新到数据库中。

想查找一个Entity,有两个类似的方法,代码如下:

Java代码

  1. Customer customer = em.find(Customer.class, 1234L)

  2. if (customer!= null) {

  3. // 处理对象

  4. }

  5. try {

  6. Customer customer = em.getReference(Customer.class, 1234L)

  7. // 处理对象

  8. } catch(EntityNotFoundException ex) {

  9. // Entity没有找到

  10. }



find方法会根据主键返回一个Entity,如果主键不存在数据库中,会返回null。getReference和find方法很类似,但是只是返回一个Entity的引用,不会返回其中的数据。它用于那些我们需要一个Entity对象和它的主键但不需要具体数据的情况。如例所示,当Entity找不到时,会有EntityNotFoundException抛出。

一个Entity可以通过EntityManager.remove()被删除,一但Entity被删除,它在数据库中也会被删除,并且脱离了EntityManager管理(detached)。此时这个对象不能再和数据库中的数据同步了。

Java代码

  1. tx.begin();

  2. em.remove(customer);

  3. tx.commit();




在之前的所有例子中,和数据库的数据的同步都是发生在事物提交时。所待执行的改变都是需要一个SQL语句的执行。例如在下面的代码中,两条insert语句会在事物提交时被执行的数据库中。

Java代码

  1. tx.begin();

  2. em.persist(customer);

  3. em.persist(address);

  4. tx.commit();


大多数情况下,这种和数据库的同步机制能满足我们程序的需要。如果我们想将对Persistence Context中数据改变立刻反映到数据库中,可以通过调用flush方法实现。或者我们想将数据库中的数据重新同步回Persistence Context,可以调用refresh方法。当应用程序在叫用了flush方法后,又调用了rollback方法,所有同步到数据库的数据又会都被回滚。
这种同步机制很像我们在sqlplus中直接执行多个SQL语句,当显性调用flush方法时,相当于执行我们已经输入的SQL语句,但没有提交事务。当tx.commit方法调用时,事物才真正的被提交。如果没有调用flush方法,则在tx.commit方法调用时先执行已经输入的SQL语句再提交事务。

Java代码

  1. tx.begin();

  2. em.persist(customer);

  3. em.flush();

  4. em.persist(address);

  5. tx.commit();


上面这个代码例子中,persist执行的顺序是要被保证的。因为在调用flush方法时,变化已经被同步到数据库中了,即SQL语句已经被执行了,如果两个persist方法顺序颠倒一下,则会出现外键约束的异常。

refresh方法实现的效果可以通过下面的例子显示出来:

Java代码

  1. Customer customer = em.find(Customer.class, 1234L)

  2. assertEquals(customer.getFirstName(), "Antony");

  3. customer.setFirstName("William");

  4. em.refresh(customer);

  5. assertEquals(customer.getFirstName(), "Antony");");



contains方法会返回一个Boolean值,用于检测当前Persistence Context中是否存在某个Entity

Java代码

  1. Customer customer = new Customer("Antony", "Balla", "tballa@mail.com");

  2. tx.begin();

  3. em.persist(customer);

  4. tx.commit();

  5. assertTrue(em.contains(customer));

  6. tx.begin();

  7. em.remove(customer);

  8. tx.commit();

  9. assertFalse(em.contains(customer));



clear方法可以清空当前Persistence Context,是所有的Entity都变成detached状态。detach方法则是只将某个Entity变成detached状态。前面已经说了detached的Entity不会和数据库中的数据再进行同步了。

Java代码

  1. Customer customer = new Customer("Antony", "Balla", "tballa@mail.com");

  2. tx.begin();

  3. em.persist(customer);

  4. tx.commit();

  5. assertTrue(em.contains(customer));

  6. em.detach(customer);

  7. assertFalse(em.contains(customer));



如果我们想使一个detached的Entity重新和数据库中的数据进行同步,可以调用merge方法。想象有这样一个场景,我们需要从数据库中取出某个对象,这个对象从持久层传到表现层之前变成了detached状态。在表现层中,Entity的一些数据发生了变化,我们将这个Entity传回持久层并让它变成managed状态以将变化反映到数据库中。

Java代码

  1. Customer customer = new Customer("Antony", "Balla", "tballa@mail.com");

  2. tx.begin();

  3. em.persist(customer);

  4. tx.commit();

  5. em.clear();

  6. // 设置一个新的值给一个detached的entity

  7. customer.setFirstName("William");

  8. tx.begin();

  9. em.merge(customer);

  10. tx.commit();



最后我们通过一张图来表示EntityManager对一个Entity的生命周期的改变。

关于 java JPA中的EntityManager是怎样的问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。

数据 数据库 方法 对象 代码 同步 状态 管理 事物 两个 语句 实例 顺序 内存 缓存 例子 可以通过 多个 情况 标识 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 服务器保护 物理防护 查看服务器当前目录下的文件大小 网络技术会问什么问题 软件开发必学单词列表 青岛培训软件开发公司 代理服务器 工作原理 网络安全总体要求a类b类 怎样加强公网服务器安全性 服务中断属于网络安全问题吗 关于青少年网络安全的建议 宁河软件开发企业 工行软件开发中心校招面试 网络安全防护典型案例 网络安全信息泄露的调查问卷 a6企业管理软件连不上服务器 汕头通讯软件开发价格比较 2台服务器如何共用一个ip 与你服务器 网络安全防范宣传单 优化数据库的查询效率 mysql如何还原数据库 杨浦区参考数据库厂家价格 陕西惠普服务器维修维保价格 明日之后策划小晨在哪服务器 数据库客体 初三政治网络安全知识 日照智慧党建软件开发专业制作 残联助听器数据库 做完网页如何连接数据库 如何将docker打包到服务器
0