Hibernate:有了 save,为什么还需要 persist?
背景
万物皆自然,每个 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?的更多相关文章
- Hibernate中save、saveorupdate、persist方法的区别
在Hibernate中,save().saveOrUpdate()和persist()都是用于将对象保存到数据库中的方法,但其中有些细微的差别.例如,save()只能INSERT记录,但是saveOr ...
- hibernate 持久化对象 save
hibernate 持久化对象 save new出来的user对象是游离状态的对象,执行session.save()方法保存后,user对象就变为持久化了,持久化的对象跟数据库表双向绑定的意思, 对象 ...
- 菜鸟学SSH(九)——Hibernate——Session之save()方法
Session的save()方法用来将一个临时对象转变为持久化对象,也就是将一个新的实体保存到数据库中.通过save()将持久化对象保存到数据库需要经过以下步骤: 1,系统根据指定的ID生成策略,为临 ...
- hibernate不调用save也保存上了
List<Instrument> insts = instService.search(search); if (insts.size() == 1) { Instrument inst ...
- Hibernate中Session.save()方法的返回值是什么
public Serializable save(Object object) Parameters: object - a transient insta ...
- 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 ...
- SpringMVC+Hibernate架构save方法事务未提交
今天同事遇到一个问题,一起研究,最后解决,让我对spring的事务管理又加深了印象. 先简单说一下项目:项目是Spring和Hibernate集成的JavaEE项目,MVC架构. 外包在service ...
- Hibernate哪点事?
1.为什么在Hibernate的实体类中要提供一个无参数的构造器这一点非常重要?每个Hibernate实体类必须包含一个 无参数的构造器, 这是因为Hibernate框架要使用Reflection A ...
- Hibernate常见面试题(转)
在Java J2EE方面进行面试时,常被问起的Hibernate面试问题,大多都是针对基于Web的企业级应用开发者的角色的.Hibernate框架在Java界的成功和高度的可接受性使得它成为了Java ...
随机推荐
- 在delphi原有控件基础上画图
var C:TControlCanvas; begin C := TControlCanvas.Create; C.Pen.Color := clRed; C.Pen.Width := ; C.Con ...
- POJ 2186 Popular cows(Kosaraju+强联通分量模板)
题目链接:http://poj.org/problem?id=2186 题目大意:给定N头牛和M个有序对(A,B),(A,B)表示A牛认为B牛是红人,该关系具有传递性,如果牛A认为牛B是红人,牛B认为 ...
- Jmeter配置元件执行顺序
一.Jmeter组件 Sampler(采样器):真正干活的,比如http 定时器:默认为毫秒. 前置处理器和后置处理器:必须在有采样器才有效,在采样器的前后执行.作关联,拿响应中的数据使用,用得比较多 ...
- vim 图册
网上看到的一些图,感觉不错,分享一下 我现在感觉配置文件,很多没有必要,反而很花哨,但是这些基础的东西,反而很高效,实在 VIM的列编辑操作 删除列 1.光标定位到要操作的地方. 2.CTRL+v 进 ...
- vue框架muse-ui官网文档主题错误毕竟【01】
在使用了element-ui后,总觉得不尽兴,再学一个响应式的muse-ui发现是个小众框架,但是我很喜欢. 指出官网文档里的主题使用描述错误. 首先,在vue-cli里安装raw-loader:np ...
- 牛客练习赛19 C-托米航空公司
思路:轮廓线dp,找bug找死我了. #include<bits/stdc++.h> #define LL long long #define fi first #define se se ...
- java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES) 解决办法
一.背景 在Spark中,将DStream写入到MySQL出现错误:java.sql.SQLException: Access denied for user 'root'@'localhost' ( ...
- cordova编译crosswalk-webview插件报错的处理办法
一直用得好好的.今天编译cordova失败了.报错如下: :processArmv7DebugManifest :processArmv7DebugResourcesERROR: In FontFam ...
- Linq简单使用
简单使用 from子查询 关联多个数据源 分组 let 子句 查询对象(上例中为list变量)为IEnumerable<T>或IQueryable<T>类型 查询返回结果同样为 ...
- Python类总结-封装(Property, setter, deleter)
Property #property #内置装饰器函数,只在面向对象中使用 from math import pi class Circle: def __init__(self,r ): self. ...