JPA学习笔记(5)——EntityManager相关

  • Persistence
  • EntityManagerFactory
  • EntityManager
    • find方法
    • getReference方法
    • persist方法
    • remove方法
    • merge方法
      • 情况1传入的对象没有id
      • 情况2传入的对象有identityManager的缓存中没有该对象数据库中没有该记录
      • 情况3传入的对象有identityManager的缓存没有该对象数据库中有该记录
      • 情况4传入的对象有identityManager的缓存有该对象
    • flush方法
    • refresh方法
    • clear
    • contains Object entity
    • isOpen
    • getTransaction
    • close
    • createQuery String qlString
    • createNamedQuery String name
    • createNativeQuery String sqlString
    • createNativeQuery String sqls String resultSetMapping

Persistence

在之前的JPA学习笔记(2)——创建JPA项目,有使用到Persistence来创建EntityManagerFactory实例

String persistenceUnitName = "jpa";
EntityManagerFactory factory = Persistence.createEntityManagerFactory(persistenceUnitName);

其实它还有一个重载方法可用

Map<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.format_sql", false);
EntityManagerFactory factory= Persistence.createEntityManagerFactory(persistenceUnitName,properties);

这里的properties,和配置文件persistence.xml中的属性是一样的。

EntityManagerFactory

EntityManagerFactory 接口主要用来创建 EntityManager 实例。该接口约定了如下4个方法:

  1. createEntityManager():用于创建实体管理器对象实例。
  2. createEntityManager(Map map):用于创建实体管理器对象实例的重载方法,Map 参数用于提供 EntityManager 的属性。
  3. isOpen():检查 EntityManagerFactory 是否处于打开状态。实体管理器工厂创建后一直处于打开状态,除非调用close()方法将其关闭。
  4. close():关闭 EntityManagerFactory 。 EntityManagerFactory 关闭后将释放所有资源,isOpen()方法测试将返回 false,其它方法将不能调用,否则将导致IllegalStateException异常。

EntityManager

以下代码省略了entityManager,entityManagerFactory,transaction的创建,关闭等过程

find方法

//查询ID为1的Order
Order order = entityManager.find(Order.class, 1);

getReference方法

Order order = entityManager.getReference(Order.class, 1);
System.out.println("-------------------------------------");
System.out.println(order);

这个方法的使用和find()一样,但是有一些区别,看下方运行结果截图:

在代码中,我先调用getReference,然后打印“- - - - - - ”,最后打印order对象

但是从截图看,是先打印“- - - - -”,然后才查询order,接着打印order。

原因:调用getReference()方法,返回的其实并不是order对象,而是一个代理。当你要使用order时,才会真正的调用查询语句来查询order对象

persist方法

Order order = new Order();
order.setOrderName("hehe");
entityManager.persist(order);
System.out.println("id="+order.getId());

执行insert操作,相当于hibernate的save()方法

从上面代码中可以看到,我们并没有给order一个id,但是在执行persist方法之后,没有从数据库查询,order.getId()也可以获取到值。这也是persist方法的一个功能:使对象由临时状态变为持久化状态。

结果截图:

但是和hibernate的save()方法有些不同:如果对象有id,则不能执行insert操作,会抛出异常

remove方法

相当于hibernate的delete()方法,但是有些不同:

remove()方法不能移除游离对象,只能移除持久化对象,什么意思呢?对比下面两段代码:

Order order = new Order();
order.setId(140);
entityManager.remove(order);

上面这段代码会抛出异常,因为order是我们自己创建的对象,也就是游离对象。

必须这样写:

Order order = new Order();
order = entityManager.find(Order.class, 140);
entityManager.remove(order);

这段代码中的order是从数据库中获取的,也就是持久化对象

hibernate的delete()方法,只要对象有Id,就可以删除

merge方法

情况1:传入的对象没有id

Order order = new Order();
order.setOrderName("hehe");
Order order2 = entityManager.merge(order);
System.out.println("order2#id:"+order2.getId());

结论:在这种情况下,调用merge方法,将返回一个新的对象(有id),并对这个新的对象执行insert操作。

情况2:传入的对象有id,entityManager的缓存中没有该对象,数据库中没有该记录

Order order = new Order();
order.setId(1000);
order.setOrderName("hehe");
Order order2 = entityManager.merge(order);
System.out.println("order#id:"+order.getId());
System.out.println("order2#id:"+order2.getId());

结论:在这种情况下,调用merge方法,将返回一个新的对象,并对该对象执行insert操作。新对象的id是数据库中这条记录的id(比如自增长的id),而不是我们自己传入的id。(其实和情况1的结果是一样的)

情况3:传入的对象有id,entityManager的缓存没有该对象,数据库中有该记录

Order order = new Order();
order.setId(170);
order.setOrderName("wahahahahah");
Order order2 = entityManager.merge(order);
System.out.println("order:"+order);
System.out.println("order2:"+order2);

调用前数据库表:

调用后结果:

结论:在这种情况下,调用merge方法,将会从数据库中查询对应的记录,生成新的对象,然后将我们传入的对象复制到新的对象,最后执行update操作。 简单来说,就是更新操作

情况4:传入的对象有id,entityManager的缓存有该对象

Order order = new Order();
order.setId(170);
order.setOrderName("xixixixi");
//通过find来将对象读入entityManager缓存
Order order3 = entityManager.find(Order.class, 170);
Order order2 = entityManager.merge(order);
System.out.println("order:"+order);
System.out.println("order2:"+order2);

结果和情况3一样,就不截图了。

结论:在这种情况下,调用merge方法,JPA会把传入的对象赋值到entityManager的缓存中的对象,然后对entityManager缓存中的对象执行update操作。(和情况3的结果一样)

flush方法

先查看数据库,有一条记录如下:

然后执行以下代码

Order order= entityManager.find(Order.class, 170);
System.out.println("order:"+order);
order.setOrderName("bbb");
//5. 提交事务
transaction.commit();

查看结果:

结果发现,JPA居然执行了update操作,把aaa改成了bbb,但是在代码中我们并没有执行update操作啊。

原因:order是通过find方法查询出来的,因此它是持久化对象,也就是说它缓存在entityManager中,当事务提交时,缓存将会被更新到数据库。

而flush方法,可以强制将缓存更新到数据库

entityManager.flush();

与之相关:

  • setFlushMode (FlushModeType flushMode):设置持久上下文环境的Flush模式。参数可以取2个枚举

    • FlushModeType.AUTO 为自动更新数据库实体,
    • FlushModeType.COMMIT 为直到提交事务时才更新数据库记录。
  • getFlushMode ():获取持久上下文环境的Flush模式。返回FlushModeType类的枚举值。

refresh方法

Order order= entityManager.find(Order.class, 170);
order= entityManager.find(Order.class, 170);

运行以上代码,发现调用了两次find,但是只执行了一次select语句,这是缓存导致的。

再看下面的代码:

Order order= entityManager.find(Order.class, 170);
entityManager.refresh(order);

只调用了一次find方法,却执行了两次select语句,这是因为refresh方法会去查看缓存中的数据状态和数据库中是否一致,因此又执行了一次select语句

clear ()

清除持久上下文环境,断开所有关联的实体。如果这时还有未提交的更新则会被撤消。

contains (Object entity):

判断一个实例是否属于当前持久上下文环境管理的实体。

isOpen ()

判断当前的实体管理器是否是打开状态。

getTransaction ()

返回资源层的事务对象。EntityTransaction实例可以用于开始和提交多个事务。

close ()

关闭实体管理器。之后若调用实体管理器实例的方法或其派生的查询对象的方法都将抛出 IllegalstateException 异常,除了getTransaction 和 isOpen方法(返回 false)。不过,当与实体管理器关联的事务处于活动状态时,调用 close 方法后持久上下文将仍处于被管理状态,直到事务完成。

createQuery (String qlString)

创建一个查询对象。

createNamedQuery (String name)

根据命名的查询语句块创建查询对象。参数为命名的查询语句。

createNativeQuery (String sqlString)

使用标准 SQL语句创建查询对象。参数为标准SQL语句字符串。

createNativeQuery (String sqls, String resultSetMapping)

使用标准SQL语句创建查询对象,并指定返回结果集 Map的 名称。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-25 03:33:36

JPA学习笔记(5)——EntityManager相关的相关文章

JPA学习笔记(8)——映射一对多关联关系

一对多关联关系 本文有很多和多对一是一样的,因此不会写得非常具体. 有看不懂的.能够參考JPA学习笔记(7)--映射多对一关联关系 Order实体类 package com.jpa.helloworld2; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; imp

MongoDB权威指南学习笔记4---查询相关的知识点

1 find find({查询条件},{"key":1,"email":1})  后面表示返回哪些键 2 可用的比较操作符 $lt , $lte,$gt,$gte 比如db.users.find({"age":{"$gte":18,"$lte":30}}) 3不等于 find(...{"key":{"$ne":"value"}} 4 in find

Java学习笔记&lt;3&gt;面向对象相关

面向对象的基本思想 从现实世界客观存在的事务出发来构造软件系统,并在系统的构造中尽可能运用人类的自然思维方式,如抽象.分类 继承.聚合.多态等. 类和对象的关系 对象中存储了类规定的数据类型,并且对象可以调用类的方法. java面向对象 <1>对象是java程序的核心,一切皆对象. <2>对象可以看成静态属性(成员变量)和动态属性(方法)的封装体. <3>类是创新同一类型对象的模版,定义了该类型对象应具有的成员变量及方法. 类的定义 成员变量可以用java语言的任何一种

MongoDB权威指南学习笔记5---索引相关的知识点

1 查看查询计划 db.user.find({"username":"xxx"}) .explain() db.doc.find({"es_y":"2014"}).explain() {  "cursor" : "BasicCursor",  "isMultiKey" : false,  "n" : 0,  "nscannedObject

spring data jpa学习笔记一:helloworld

在学习 JPA Spring Data之前,我们有必要了解一下JPA和Spring Data. JPA JPA全称Java Persistence API.即java持久化规范.JPA通过注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. Spring Data Spring Data是Spring框架的一个子项目,就像Spring MVC是Spring的一部分一样.使得数据库访问变得方便和快捷.Spring Data 支持JPA. JPA Spring Data J

学习笔记之html5相关内容

写一下昨天学习的html5的相关内容,首先谈下初次接触html5的感受.以前总是听说html5是如何的强大,如何的将要改变世界.总是充满了神秘感.首先来谈一下我接触的第一个属性是  input的里面的一个属性是 type="email".以前用html的时候,type是有很多类型的,有text,password,summit.就是没听说过email.当得知这个email是验证输入的内容是否为email格式的时候.我顿时兴奋了.以前接触到html的时候,如果要验证输入内容时,是需要写js

Spring入门---JPA学习笔记

用了一段时间的Spring,到现在也只是处于会用的状态,对于深入一点的东西都不太了解.所以决定开始深入学习Spring. 本文主要记录JPA学习.在学习JPA之前,需要了解一些ORM的概念. ORM概念: 对象关系映射ORM(Object/Relation Mapping)是一种为了解决面向对象和关系数据之间存在互不匹配现象的技术(范式不匹配).简而言之,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到数据库中.本质上是将数据从一种形式转换到另外一种形式.(个人考虑:

JPA学习笔记

一.JPA基础1.1 JPA基础JPA: java persistence api 支持XML.JDK5.0注解俩种元数据的形式,是SUN公司引入的JPA ORM规范 元数据:对象和表之间的映射关系 实体: entity,需要使用Javax.persistence.Entity注解或xml映射,需要无参构造函数,类和相关字段不能使用final关键字 游离状态实体以值方式进行传递,需要serializable JPA是一套规范.有很多框架支持(如Hibernate3.2以上.Toplink,一般用

JPA学习笔记(16)——JPA高级

1.JPA的实体生命周期: JPA的实体有以下4中生命周期状态: (1).New:瞬时对象,尚未有id,还未和Persistence Context建立关联的对象. (2).Managed:持久化受管对象,有id值,已经和Persistence Context建立了关联的对象. (3).Datached:游离态离线对象,有id值,但没有和Persistence Context建立关联的对象. (4).Removed:删除的对象,有id值,尚且和Persistence Context有关联,但是已