在 JPA 规范中, EntityManager 是完成持久化操作的核心对象。
实体作为普通 Java 对象,只有在调用 EntityManager 将其持久化后才会变成持久化对象。
EntityManager 对象在一组实体类与底层数据源之间进行 O/R 映射的管理。它可以用来管理和更新 Entity Bean, 根椐主键查找 Entity Bean, 还可以通过JPQL语句查询实体。
其源码如下:
**
* Interface used to interact with the persistence context.
*//这里讲述了EntityManager的作用!!!
* An EntityManager
instance is associated with
* a persistence context. A persistence context is a set of entity
* instances in which for any persistent entity identity there is
* a unique entity instance. Within the persistence context, the
* entity instances and their lifecycle are managed.
* The EntityManager
API is used
* to create and remove persistent entity instances, to find entities
* by their primary key, and to query over entities.
*
*
The set of entities that can be managed by a given
* EntityManager
instance is defined by a persistence
* unit. A persistence unit defines the set of all classes that are
* related or grouped by the application, and which must be
* colocated in their mapping to a single database.
*
* @see Query
* @see TypedQuery
* @see CriteriaQuery
* @see PersistenceContext
*
* @since Java Persistence 1.0
*/
public interface EntityManager {
//...
}
实体的状态:
新建状态: 新创建的对象,尚未拥有持久性主键;
持久化状态:已经拥有持久性主键并和持久化建立了上下文环境;
游离状态:拥有持久化主键,但是没有与持久化建立上下文环境;
删除状态: 拥有持久化主键,已经和持久化建立上下文环境,但是从数据库中删除。
find (Class
:返回指定的 OID 对应的实体类对象。
第一个参数为被查询的实体类类型,第二个参数为待查找实体的主键值。
如果这个实体存在于当前的持久化环境,则返回一个被缓存的对象;否则会创建一个新的 Entity, 并加载数据库中相关信息;若 OID 不存在于数据库中,则返回一个 null。
实例如下:
public class JPATest {
private EntityManagerFactory entityManagerFactory;
private EntityManager entityManager;
private EntityTransaction transaction;
@Before
public void init(){
entityManagerFactory = Persistence.createEntityManagerFactory("jpa-1");
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
}
@After
public void destroy(){
transaction.commit();
entityManager.close();
entityManagerFactory.close();
}
//类似于hibernate中session的get方法--先创建
@Test
public void testFind(){
Customer customer = entityManager.find(Customer.class,1);
System.out.println(customer.getClass().getName());
System.out.println("-----------------------------------------------");
System.out.println(customer.toString());
}
如果数据库中没有对应的信息,返回null:
getReference (Class
:与find()方法类似。
不同的是:如果缓存中不存在指定的 Entity, EntityManager 会创建一个 Entity 类的代理,但是不会立即加载数据库中的信息,只有第一次真正使用此 Entity 的属性才加载,所以如果此 OID 在数据库不存在,getReference() 不会返回 null 值, 而是抛出EntityNotFoundException。
实例如下:
//类似于hibernate中session的load方法--需要的时候再创建
@Test
public void testGetReference(){
Customer customer = entityManager.getReference(Customer.class, 1);
// 这里是代理对象 com.atguigu.jpa.helloworld.Customer_$$_javassist_0,容易出现懒加载异常
System.out.println(customer.getClass().getName());
System.out.println("-----------------------------------------------");
// transaction.commit();
// entityManager.close();
System.out.println(customer.toString());
}
如果数据库中没有对应的信息,抛出异常:
懒加载异常:
persist (Object entity)
:用于将新创建的 Entity 纳入到 EntityManager 的管理。该方法执行后,传入 persist() 方法的 Entity 对象转换成持久化状态。
如果传入 persist() 方法的 Entity 对象已经处于持久化状态,则 persist() 方法什么都不做。
如果对删除状态的 Entity 进行 persist() 操作,会转换为持久化状态。
如果对游离状态的实体执行 persist() 操作,可能会在 persist() 方法抛出 EntityExistException(也有可能是在flush或事务提交后抛出)。
实例如下:
//类似于hibernate中session的save方法,使对象由临时状态变为持久化状态
//和hibernate的save方法的不通之处:若对象由id,则不能执行持久化insert操作,而会抛出异常
@Test
public void testPersist(){
Customer customer = new Customer();
// customer.setId(3);
customer.setAge(11);
customer.setBirth(new Date());
customer.setCreatedTime(new Date());
customer.setEmail("[email protected]");
customer.setLastName("jane");
entityManager.persist(customer);
System.out.println("-----------------------------------------------");
System.out.println(customer.toString());
}
如果为entity设置了id,则会抛出异常:
remove (Object entity):删除实例。
如果实例是被管理的,即与数据库实体记录关联,则同时会删除关联的数据库记录。
代码如下:
//类似于hibernate中session的delete方法,把对象对应的记录从数据库删除
//但注意该方法只能移除持久化对象,而hibernate对象的delete方法还可以移除游离对象
@Test
public void testRemove(){
Customer customer = entityManager.find(Customer.class, 2);
entityManager.remove(customer);
System.out.println("-----------------------------------------------");
System.out.println(customer.toString());
}
merge (T entity):merge() 用于处理 Entity 的同步。即数据库的插入和更新操作。
原理示意图如下:
测试一如下,传入临时对象,无id:
/**
* 1.若传入的是一个临时对象,则会创建一个新对象,把临时对象的属性复制到新对象中,然后对新对象进行持久化操作
* 即,新对象将有id,但以前的临时对象没有id
*/
@Test
public void testMerge1(){
Customer customer = new Customer();
customer.setAge(11);
customer.setBirth(new Date());
customer.setCreatedTime(new Date());
customer.setEmail("[email protected]");
customer.setLastName("jane");
Customer customer2 = entityManager.merge(customer);
System.out.println("customer#id :"+customer.getId());
System.out.println("customer2#id :"+customer2.getId());
}
测试一如下,传入临时对象:
测试二如下,传入游离对象,有id且数据库无对应id,EntityManager中无该对象:
这里执行的时插入语句。
测试三如下,传入游离对象,有id且数据库有对应id,EntityManager中无该对象:
这里执行的时更新语句。
测试四如下,传入游离对象,EntityManager有该对象:
/**
* 3.若传入的对象是一个游离对象,即对象有OID;
* em缓存中存在该对象,jpa会把游离对象复制到缓存中的对象,
* 然后进行更新操作
*
*/
@Test
public void testMerge3(){
Customer customer = new Customer();
customer.setAge(11);
customer.setBirth(new Date());
customer.setCreatedTime(new Date());
customer.setEmail("[email protected]");
customer.setLastName("jane4");
customer.setId(4);
System.out.println("customer :"+customer.toString());
Customer customer2 = entityManager.find(Customer.class, 4);
System.out.println("customer2 :"+customer2.toString());
Customer merge = entityManager.merge(customer);
System.out.println("merge :"+merge.toString());
}
控制台结果如下:
顾名思义,强制刷新。同步持久上下文环境,即将持久上下文环境的所有未保存实体的状态信息保存到数据库中。
同流、缓存中的flush方法意义相同,将数据强制输出或更新。
setFlushMode (FlushModeType flushMode):设置持久上下文环境的Flush模式。参数可以取2个枚举
FlushModeType.AUTO 为自动更新数据库实体,
FlushModeType.COMMIT 为直到提交事务时才更新数据库记录。
getFlushMode ():获取持久上下文环境的Flush模式。返回FlushModeType类的枚举值。
示例如下:
/**
* ͬ hibernate的 Session 的 flush方法
*/
@Test
public void testFlush(){
Customer customer = entityManager.find(Customer.class, 1);
System.out.println(customer);
customer.setLastName("BB");
entityManager.flush();
}
控制台输出结果如下:
refresh (Object entity):
用数据库实体记录的值更新实体对象的状态,即更新实例的属性值。
即,刷新内存中对象的属性。
示例如下:
/**
* ͬ hibernate 的 Session 的 refresh 方法.
*/
@Test
public void testRefresh(){
Customer customer = entityManager.find(Customer.class, 1);
customer = entityManager.find(Customer.class, 1);
customer.setAge(100);
System.out.println(customer.toString());
entityManager.refresh(customer);
System.out.println(customer.toString());
}
控制台输出如下:
clear ():清除持久上下文环境,断开所有关联的实体。如果这时还有未提交的更新则会被撤消。
判断一个实例是否属于当前持久上下文环境管理的实体。
判断当前的实体管理器是否是打开状态。
返回资源层的事务对象。
EntityTransaction实例可以用于开始和提交多个事务。
关闭实体管理器。之后若调用实体管理器实例的方法或其派生的查询对象的方法都将抛出 IllegalstateException 异常,除了getTransaction 和 isOpen方法(返回 false)。
不过,当与实体管理器关联的事务处于活动状态时,调用 close 方法后持久上下文将仍处于被管理状态,直到事务完成。
createQuery (String qlString):创建一个查询对象。
createNamedQuery (String name):根据命名的查询语句块创建查询对象。参数为命名的查询语句。
createNativeQuery (String sqlString):使用标准 SQL语句创建查询对象。参数为标准SQL语句字符串。
createNativeQuery (String sqls, String resultSetMapping):使用标准SQL语句创建查询对象,并指定返回结果集 Map的 名称。