背景

万物皆自然,每个 API 的设计,无论是否正确,都有其意图。因此,在学习某些框架的时候,我们需要经常思考:这个 API 的设计意图是啥?

本文来探讨一下 Session 中 persist 的设计意图。

官方注释

save

     /**
* Persist the given transient instance, first assigning a generated identifier. (Or
* using the current value of the identifier property if the <tt>assigned</tt>
* generator is used.) This operation cascades to associated instances if the
* association is mapped with {@code cascade="save-update"}
*
* @param object a transient instance of a persistent class
*
* @return the generated identifier
*/
public Serializable save(Object object);

persist

     /**
* Make a transient instance persistent. This operation cascades to associated
* instances if the association is mapped with {@code cascade="persist"}
* <p/>
* The semantics of this method are defined by JSR-220.
*
* @param object a transient instance to be made persistent
*/
public void persist(Object object);

解释

save 因为需要返回一个主键值,因此会立即执行 insert 语句,而 persist 在事务外部调用时则不会立即执行 insert 语句,在事务内调用还是会立即执行 insert 语句的。

看 persist 的注释会觉得其不会立即执行 insert 语句,为何 在事务内调用会立即执行 insert 语句,后面再分析。

测试

SessionHelper

 package demo;

 import org.hibernate.*;
import org.hibernate.cfg.*; public final class SessionHelper {
private static SessionFactory factory; public static void execute(SessionAction action) {
execute(action, false);
} public static void execute(SessionAction action, boolean beforeTransaction) {
Session session = openSession();
try {
if (beforeTransaction) {
System.out.println("action");
action.action(session);
} System.out.println("begin transaction");
session.beginTransaction();
if (!beforeTransaction) {
System.out.println("action");
action.action(session);
} System.out.println("flush and commit");
session.flush();
session.getTransaction().commit();
} catch (Exception ex) {
session.getTransaction().rollback();
} finally {
session.close();
}
} @SuppressWarnings("deprecation")
public static Session openSession() {
if (factory == null) {
factory = new Configuration().configure().buildSessionFactory();
} return factory.openSession();
}
}

save

 package demo;

 import model.*;

 import org.hibernate.*;
/*
* save 会导致 insert 语句的立即执行。
*/
public class SaveDemo implements Demo { @Override
public void run() {
SessionHelper.execute(new SessionAction() { @Override
public void action(Session session) {
User user = new User();
user.setUsername("woshishui");
user.setPassword("123456"); session.save(user);
} });
} }

输出结果

 begin transaction
action
Hibernate:
/* insert model.User
*/ insert
into
USERS
(USERNAME, PASSWORD)
values
(?, ?)
flush and commit

persis in transactiont

 package demo;

 import model.*;

 import org.hibernate.*;

 /*
* persist 在事务中执行,会导致 insert 语句的立即执行。
*/
public class PersisInTransactiontDemo implements Demo { @Override
public void run() {
SessionHelper.execute(new SessionAction() { @Override
public void action(Session session) {
User user = new User();
user.setUsername("woshishui");
user.setPassword("123456"); session.persist(user);
} });
} }

输出结果

 begin transaction
action
Hibernate:
/* insert model.User
*/ insert
into
USERS
(USERNAME, PASSWORD)
values
(?, ?)
flush and commit

persis before transactiont

 package demo;

 import model.*;

 import org.hibernate.*;

 /*
* persist 不在事务中执行,不会导致 insert 语句的立即执行,而是在 flush 时执行 insert 语句。
*/
public class PersisBeforeTransactiontDemo implements Demo { @Override
public void run() {
SessionHelper.execute(new SessionAction() { @Override
public void action(Session session) {
User user = new User();
user.setUsername("woshishui");
user.setPassword("123456"); session.persist(user);
} }, true);
} }

输出结果

 action
begin transaction
flush and commit
Hibernate:
/* insert model.User
*/ insert
into
USERS
(USERNAME, PASSWORD)
values
(?, ?)

分析

为何 persist 在事务内和事务外表现的行为不同呢?为何这样设计?目前还没有查到官方的第一手资料(刚学习 Java 和 Hibernate),我的猜测是:事务外的 persist 是为了应对长事务,事务内的 persist 是为了和 save 保持一个语义

备注

学习 Hibernate 的过程也相当于从新学习了一遍 EntityFramework,换个视角总有好处。

Hibernate:有了 save,为什么还需要 persist?的更多相关文章

  1. Hibernate中save、saveorupdate、persist方法的区别

    在Hibernate中,save().saveOrUpdate()和persist()都是用于将对象保存到数据库中的方法,但其中有些细微的差别.例如,save()只能INSERT记录,但是saveOr ...

  2. hibernate 持久化对象 save

    hibernate 持久化对象 save new出来的user对象是游离状态的对象,执行session.save()方法保存后,user对象就变为持久化了,持久化的对象跟数据库表双向绑定的意思, 对象 ...

  3. 菜鸟学SSH(九)——Hibernate——Session之save()方法

    Session的save()方法用来将一个临时对象转变为持久化对象,也就是将一个新的实体保存到数据库中.通过save()将持久化对象保存到数据库需要经过以下步骤: 1,系统根据指定的ID生成策略,为临 ...

  4. hibernate不调用save也保存上了

    List<Instrument> insts = instService.search(search); if (insts.size() == 1) { Instrument inst ...

  5. Hibernate中Session.save()方法的返回值是什么

    public   Serializable   save(Object   object)     Parameters:     object   -   a   transient   insta ...

  6. org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save()

    org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before ...

  7. SpringMVC+Hibernate架构save方法事务未提交

    今天同事遇到一个问题,一起研究,最后解决,让我对spring的事务管理又加深了印象. 先简单说一下项目:项目是Spring和Hibernate集成的JavaEE项目,MVC架构. 外包在service ...

  8. Hibernate哪点事?

    1.为什么在Hibernate的实体类中要提供一个无参数的构造器这一点非常重要?每个Hibernate实体类必须包含一个 无参数的构造器, 这是因为Hibernate框架要使用Reflection A ...

  9. Hibernate常见面试题(转)

    在Java J2EE方面进行面试时,常被问起的Hibernate面试问题,大多都是针对基于Web的企业级应用开发者的角色的.Hibernate框架在Java界的成功和高度的可接受性使得它成为了Java ...

随机推荐

  1. IDEA添加其他项目为库文件的方法

    IDEA添加其他项目为库文件的方法 2014年1月23日星期四 20:46 问题:如果我通过引用项目修改了被引用库项目的源代码,他没法自动编译,所以不会立即反应到引用项目. 在Eclipse中,很简单 ...

  2. 学习笔记----float后不与前面元素同行解决办法。

    <li>文本<span> 16-08-17</span></li> 当非float的元素和float的元素在一起的时候(如上代码), 如果非float元 ...

  3. redis关闭保护模式

    1. set key出现的报错 在192.168.56.57客户端登录192.168.56.56的redis服务器时,报错如下: [root@localhost src]# ./redis-cli - ...

  4. 七 使用list和tuple

    list Python内置的一种数据类型是列表:list.list是一种有序的集合,可以随时添加和删除其中的元素. 比如,列出班里所有同学的名字,就可以用一个list表示: >>> ...

  5. 【Sql Server】Sql语句整理

    use Person <--添加约束--> Alter table Student alter column Sno ) not null; Alter table Student Add ...

  6. postman自动生成签名

    查看详细图文教程↓ 一.全局变量方式 1. 在全局变量添加key:value分别是autoSign和var sign={toUnicode:function(s){return s.replace(/ ...

  7. SCU 4443 Range Query

    二分图最大匹配,枚举. 可以计算出每一个位置可以放哪些数字,每个数字可以放在哪些位置,这样就可以建二分图了. 如果二分图最大匹配不到$n$,则无解.否则构造字典序最小的解,可以枚举每一位放什么数字,然 ...

  8. TCP的那些事-2

    这篇文章是下篇,所以如果你对TCP不熟悉的话,还请你先看看上篇<TCP的那些事儿(上)> 上篇中,我们介绍了TCP的协议头.状态机.数据重传中的东西.但是TCP要解决一个很大的事,那就是要 ...

  9. Hibernate *.hbm.xml对象关系映射文件详解

    在hibernate中表与pojo对象是一一对应的,通过hbm文件将数据库表与实体关联起来,本文将对hbm文件进行介绍. pojo对象:提供了公共的无参构造方法 ,通过反射产生对象.          ...

  10. Java 基础总结--反射的基本操作

    一.反射的概念 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为 ...