背景

万物皆自然,每个 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. csu 1556(快速幂)

    1556: Jerry's trouble Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 787  Solved: 317[Submit][Statu ...

  2. 邀请用户进TestFlight 体验 App 的测试版本

    iphone手机用户,在工作中常见到,APP版本现在是Beta阶段(iOS版本),需要邀请一些用户来体验新版本,在版本上线前提出更好的建议及时进行修改,此时用到了testflight,很方便的通过邀请 ...

  3. [loj6039]「雅礼集训 2017 Day5」珠宝 dp+决策单调性+分治

    https://loj.ac/problem/6039 我们设dp[i][j]表示考虑所有价值小于等于i的物品,带了j块钱的最大吸引力. 对于ci相同的物品,我们一定是从大到小选k个物品,又发现最大的 ...

  4. 搭建简单的CGI应用程序

    原文来源于<核心编程3>第10章web编程 一.静态文件+脚本文件 1.首先开启cgiweb服务器 python2 -m CGIHTTPServer 8000 看到如下反应 2.服务器目录 ...

  5. 微软企业库5.0 学习之路——扩展学习篇、库中的依赖关系注入(重构 Microsoft Enterprise Library)[转]

    这篇文章是我在patterns & practices看到的一篇有关EntLib5.0的文章,主要介绍了EntLib5.0的这次的架构变化由来,觉得很不错,大家可以看一下! 在过去几年中,依赖 ...

  6. JS 数组求 最大值、最小值、平均值以及求和方法

    function arrMaxNum2(arr) { return Math.max.apply(null, arr); } function arrMinNum2(arr) { return Mat ...

  7. App启动广告

    需求: App启动的时候获得广告图片链接,如果已经存在,判断是否和本地的相同,不相同才去下载到本地. 流程图: 这些都在广告页的前一个页面操作(logo页或者Application) import a ...

  8. Python数据类型-列表(list)增删改查

    1.添加元素 添加单个元素:使用append(object)函数可以为列表添加单个元素,参数object为对象:也就是说所有Python的对象都可以添加到列表中. 添加多个元素(合并列表):使用ext ...

  9. Mybatis源码分析之参数处理

    Mybatis对参数的处理是值得推敲的,不然在使用的过程中对发生的一系列错误直接懵逼了. 以前遇到参数绑定相关的错误我就是直接给加@param注解,也稀里糊涂地解决了,但是后来遇到了一些问题推翻了我的 ...

  10. vmware12安装centos7系统详解

    1.首先需要准备的工具有vmware12和contos7的系统. vmvare12下载地址: http://pan.baidu.com/s/1i5vH50D contos7我自己使用的为1511版本. ...