背景

万物皆自然,每个 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. hdu 1597(矩阵快速幂)

    1597: 薛XX后代的IQ Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 228  Solved: 55[Submit][Status][Web Bo ...

  2. 打开Office2007弹出“向程序发送命令时出现问题” 解决方案

    打开Office2007弹出“向程序发送命令时出现问题” 解决方案,试了很多方案,最终还是这种方法帮我解决了问题,分享下,以下地址便是: http://club.excelhome.net/threa ...

  3. 纯js的N级联动列表框 —— 基于jQuery

    多个列表框联动,不算是啥大问题,但是却挺麻烦,那么怎么才能够尽量方便一点呢?网上搜了一下,没发现太好用的,于是就自己写了一个.基于jQuery,无限级联动,支持下拉列表框和列表框. 先说一下步骤和使用 ...

  4. winEDT 9.0 完美破解

    options-->options interface... --> advance configuration... -->event handlers --> Exit,并 ...

  5. LoadRunner常用函数汇总

    LoadRunner命令汇总 . 命令行分析函数 (1)lr_get_attrib_double() 检索脚本命令行中使用的double类型变量 (2)lr_get_attrib_string() 检 ...

  6. bzoj 1109

    思路:我们考虑dp[ i ] 表示的是 i 在指定位置上 的最大个数, dp[ i ] = max(dp[ j ] + 1) j需要满足3个条件 1. j < i 2. a[ j ] < ...

  7. poj1475 Pushing Boxes(BFS)

    题目链接 http://poj.org/problem?id=1475 题意 推箱子游戏.输入迷宫.箱子的位置.人的位置.目标位置,求人是否能把箱子推到目标位置,若能则输出推的最少的路径,如果有多条步 ...

  8. poj1040 Transportation(DFS)

    题目链接 http://poj.org/problem?id=1040 题意 城市A,B之间有m+1个火车站,第一站A站的编号为0,最后一站B站的编号为m,火车最多可以乘坐n人.火车票的票价为票上终点 ...

  9. Disruptor Java版和.NET版的区别

    The main differences comes from the fact that .NET supports structs (value types), Java doesn't. In ...

  10. 机器寻径引导算法C#(最短路径表)

    using System; using System.Collections; using System.Collections.Generic; using System.Linq; using S ...