Hibernate Session和Jpa EntityManager

简介: 本文主要比较一下二者操作实体类的方法的关系和区别。本文适用 Hibernate:4.3.11.Final 和 spring-data-jpa:1.10.4.RELEASE 。

本文主要比较一下二者操作实体类的方法的关系和区别。

本文适用 Hibernate:4.3.11.Final 和 spring-data-jpa:1.10.4.RELEASE 。

创建方式

Session:

Configuration configuration=new Configuration().configuration();

ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();

SessionFactory sessionFactory=configuration.buildSessionFactory(serviceRegistry);

Session session=factory.openSession();

Transaction transaction=session.beginTransaction();
//to do sth.
transaction.commit();
session.cose();
sessionFactory.close();

EntityManager:

EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory("persistenceUnitName");

EntityManager entityManager=entityManagerFactory.createEntityManager();

EntityTransaction entityTransaction=entityManager.createEntityTransaction();
entityTransaction.begin();
//to do sth.
entityTransaction.commit();
entityManager.close();
entityManagerFactory.close();

二者的联系

SessionFactory 对应 EntityManagerFactory;

Session 对应 EntityManager;

SessionFactory是线程安全的,Session不是线程安全的;

EntityManager 是线程安全的;

关于配置文件

Hibernate需要一个配置文件:hibernate.xml,文件在classpath可以访问即可。

JPA需要一个persistence.xml,文件必须是META/persistence.xml

如果整合Spring的话,就让他们随风去吧。

方法对比

session的方法:

flush()
evict()
load()
save()
saveOrUpdate()
update()
merge()
persist()
delete()
refresh()
get()

EntityManager的方法:

persist()
merge()
remove()
find()
flush()
refresh()
detach()
getReference()

从上面看出,jpa操作实体类的方法少了很多。

为了看起来不太混乱,以下用S代替Session,E代替EntityManager.

S.evict() = E.detach()

二者对应。

S.load() = E.getReference()

执行查询时返回代理对象,这是懒加载。spring-data-jpa中对应getOne();

如果数据库中没有对应的记录,抛异常。

注:这里spring-data-jpa又任性了,getOne()不是对应get(),注意。还有更任性的,如果对象在缓存中的话,那么getOne就会返回实体对象,否则返回代理对象。

S.get() = E.find()

执行查询时返回实体对象,立即加载。spring-data-jpa中对应findOne();

如果数据库中没有对应的记录,则返回null。

S.persist() = E.persist()

二者对应。

S.save() ≈ E.persist()

EntityManager没有save方法。

区别:

调用前的实体对象,如果主键使用setter设置了值,E.persist()会抛异常。而S.save()不会抛异常,只是会忽略。

S.delete() ≈ E.remove()

区别:delete()可以移出持久化对象和游离对象,而remove只能移出持久化对象,否则会抛异常。

S.saveOrUpdate()+S.merge() ≈ E.merge()

E.merge()当实体对象O1为临时对象,会创建一个新对象O2,执行insert操作,并返回这个新对象,相当于S.saveOrUpdate()。此时O2为持久化对象,而O1仍然是游离对象。

E.merge()当实体对象O1位游离对象,即主键不为空:
首先查询缓存中是否有该主键对应的持久化对象,如果有,将缓存中的对象提取为O2,然后根据O1的值修改O2,并对O2执行update,返回O2.

如果缓存中不存在,那么就发送一条select去查询数据库中是否有持久化对象,如果存在,查询返回的持久化对象O2,根据O1修改O2的属性,并对O2执行update;否则,新建一个临时对象O2,复制O1的属性,并对O2执行insert,返回O2。

以上E.merge()类似于S.saveOrUpdate(),下面看一下Hibernate中的一种情况:

@Test
@org.springframework.transaction.annotation.Transactional
public void testHibernate(){
  Session session=sessionFactory.getCurrentSession();
  Transaction transaction = session.beginTransaction();
  User u1=(User) session.get(User.class, 1);
  User u2=new User();
  u2.setId(1);
  session.saveOrUpdate(u2);
  System.out.println(u1==u2);
  transaction.commit();
  session.close();
}

Hibernate不允许缓存中存在两个持久化对象对应同一个主键。

而JPA中不抛异常:

@Test
@Transactional
public void testJpa(){
  User u1=entityManager.find(User.class, 1);
  User u2=new User();
  u2.setId(1);
  u2.setUserName("Jack");
  User u3=entityManager.merge(u2);
  System.out.println(Arrays.asList(u1));
  System.out.println(Arrays.asList(u2));
  System.out.println(u1==u2);
  System.out.println(u1==u3);
}

这是由于JPA不是在缓存中加载了第二个同一主键的实体对象,而是进行了实体对象的拷贝。

再看S.merge():

@Test
@org.springframework.transaction.annotation.Transactional
public void testHibernateMerge(){
  Session session=sessionFactory.getCurrentSession();
  Transaction transaction = session.beginTransaction();
  User u1=(User) session.get(User.class, 1);
  User u2=new User();
  u2.setId(1);
  User u3=(User) session.merge(u2);
  System.out.println(u1==u2);
  System.out.println(u1==u3);
  transaction.commit();
  session.close();
}

这样是可以的,也就是说在这种情况下,S.merge()=E.merge()。

目录
相关文章
|
27天前
|
SQL Java 数据库连接
springBoot+Jpa(hibernate)数据库基本操作
springBoot+Jpa(hibernate)数据库基本操作
29 0
|
3月前
|
Java 数据库连接 数据库
携手前行:在Java世界中深入挖掘Hibernate与JPA的协同效应
【8月更文挑战第31天】Java持久化API(JPA)是一种Java规范,为数据库数据持久化提供对象关系映射(ORM)方法。JPA定义了实体类与数据库表的映射及数据查询和事务控制方式,确保不同实现间的兼容性。Hibernate是JPA规范的一种实现,提供了二级缓存、延迟加载等丰富特性,提升应用性能和可维护性。通过结合JPA和Hibernate,开发者能编写符合规范且具有高度可移植性的代码,并利用Hibernate的额外功能优化数据持久化操作。
39 0
|
3月前
|
Java 数据库连接 数据库
Spring Data JPA 与 Hibernate 之区别
【8月更文挑战第21天】
69 0
|
3月前
|
SQL Java 数据库连接
Hibernate 和 JPA 有什么区别?
【8月更文挑战第21天】
187 0
|
3月前
|
缓存 安全 Java
|
3月前
|
缓存 安全 Java
Hibernate 中的 Session 是线程安全的吗?
【8月更文挑战第21天】
40 0
|
3月前
|
缓存 安全 Java
Hibernate 中的 Session 是什么?
【8月更文挑战第21天】
21 0
|
5月前
|
Java 数据库连接 数据库
JPA和Hibernate的乐观锁与悲观锁
木头左讲解JPA和Hibernate中的乐观锁与悲观锁。乐观锁在并发更新少、冲突处理成本高、数据一致性要求不严的场景下适用,利用`@Version`注解防止冲突。而悲观锁适合并发更新频繁、处理冲突成本低、需高度数据一致性的场景,通过`@Lock`注解实现锁机制。选择合适的锁策略对提升数据库性能和保证数据一致性至关重要。
JPA和Hibernate的乐观锁与悲观锁
|
5月前
|
Java 数据库连接 API
解锁你的数据库:JPA和Hibernate的乐观锁与悲观锁
本文由木头左介绍JPA和Hibernate中的乐观锁与悲观锁。乐观锁假设无冲突,通过`@Version`注解防止并发更新,适用于更新不频繁、处理冲突成本高、数据一致性要求不高的场景。悲观锁假设有冲突,利用`@Lock`注解实现加锁,适用于并发更新频繁、处理冲突成本低、数据一致性要求高的情况。选择哪种锁取决于具体需求。
解锁你的数据库:JPA和Hibernate的乐观锁与悲观锁
|
5月前
|
缓存 Java 数据库连接
深入理解Java中的JPA与Hibernate
深入理解Java中的JPA与Hibernate