背景

万物皆自然,每个 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. Linux命令之ip命令

    linux的ip命令和ifconfig类似,但前者功能更强大,并旨在取代后者.使用ip命令,只需一个命令,你就能很轻松地执行一些网络管理任务.ifconfig是net-tools中已被废弃使用的一个命 ...

  2. ORA-12537: TNS:connection closed错误处理过程

    https://blog.csdn.net/mchdba/article/details/50018571

  3. GUC-2 原子性

    import java.util.concurrent.atomic.AtomicInteger; /* * 一.i++ 的原子性问题:i++ 的操作实际上分为三个步骤“读-改-写” * int i ...

  4. SRILM的安装方法

    官网 网上搜的安装教程:SRILM的安装方法 最近做的一个项目要用到语言模型,在网上找了一些开源的工具包试了一下.废话不多说,下面直接介绍一下SRILM的安装方法. 我实在ubuntu14.04底下使 ...

  5. bzoj 1115 转换+阶梯博弈

    思路:我打了半天的表找规律....  我们将每两个数的差值看成一堆堆石子,那么题目实际上就变为了 从当前堆可以拿出一些石子放到下一堆里去,就变成了一个阶梯博弈... #include<bits/ ...

  6. Redis实战(五)

    删除Redis中数据 using (var redisClient = RedisManager.GetClient()) { var user = redisClient.GetTypedClien ...

  7. React学习笔记2017-12-31

    课程:https://coding.imooc.com/class/chapter/150.html 第一章:介绍 第二章:知识储备 React开发环境 1.安装Nodejs 2.安装Visual S ...

  8. windows 10 下安装python 2.7

    下载msi的安装包: https://www.python.org/ftp/python/2.7.8/python-2.7.8.msi [incorrect] PS C:\Python27> . ...

  9. Python实现简单的API接口

    get方法 代码实现   # coding:utf-8       import json   from urlparse import parse_qs   from wsgiref.simple_ ...

  10. getattr(sys.modules[__name__], func_name)

    有时我们需要将一个文件的信息(类.函数及变量)保存到文件,我们不能直接保存函数对象,而是将其转化为fn.__name__,问题来了,当我们想通过读取文件的形式重新配置这些类.函数时,该如何把这些字符串 ...