温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java JPA中的EntityManager是怎样的

发布时间:2021-12-01 15:19:27 来源:亿速云 阅读:313 作者:柒染 栏目:云计算

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

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

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

Java代码   java JPA中的EntityManager是怎样的  

  1. @Entity   

  2. public class Book {  

  3.   

  4.     @Id  

  5.     @GeneratedValue  

  6.     private Long id;  

  7.   

  8.     private String title;  

  9.     private Float price;  

  10.     private String description;  

  11.     private String isbn;  

  12.     private Integer nbOfPage;  

  13.     private Boolean illustrations;  

  14.   

  15.     // Getters, setters  

  16. }  



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

java JPA中的EntityManager是怎样的 

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

java JPA中的EntityManager是怎样的 
  
  在我们介绍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访问同一个数据库的实例如下图: 

java JPA中的EntityManager是怎样的 

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

Java代码   java JPA中的EntityManager是怎样的  

  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代码   java JPA中的EntityManager是怎样的  

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

  2. if (customer!= null) {  

  3. // 处理对象  

  4. }  

  5.   

  6. try {  

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

  8. // 处理对象  

  9. } catch(EntityNotFoundException ex) {  

  10. // Entity没有找到  

  11. }  



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

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

Java代码   java JPA中的EntityManager是怎样的  

  1. tx.begin();  

  2. em.remove(customer);  

  3. tx.commit();  




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

Java代码   java JPA中的EntityManager是怎样的  

  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代码   java JPA中的EntityManager是怎样的  

  1. tx.begin();  

  2. em.persist(customer);  

  3. em.flush();  

  4. em.persist(address);  

  5. tx.commit();  


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

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

Java代码   java JPA中的EntityManager是怎样的  

  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代码   java JPA中的EntityManager是怎样的  

  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代码   java JPA中的EntityManager是怎样的  

  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代码   java JPA中的EntityManager是怎样的  

  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是怎样的

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

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI