Hibernate:session.flush与transaction.commit

本文通过一个简单的Hibernate事务示例,详细解析了Hibernate如何处理数据的插入操作,包括缓存管理、SQL语句生成及执行时机等核心过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

session save 方法为例来看一个简单、完整的事务流程,如下是代码片段:

…………………………………………………………………………

Session session = sessionFactory .openSession();

Transaction tx = session.beginTransaction();

session.save(customer);// 之前已实例化好了的一个对象

tx.commit();

…………………………………………………………………………

示例很简单,就是向数据库中插入一条顾客信息,这是一个最简单的数据库事务。在这个简单的过程中, Hibernate 为我们做了一些什么事情呢?为了更好的观察,我们将 Hibernate show_sql 属性设置为 true ,然后运行我们的程序,控制台打印出如下信息:

Hibernate: select max(ID) from CUSTOMER

Hibernate: insert into CUSTOMER (NAME, EMAIL, PASSWORD, PHONE, ADDRESS, SEX, IS_MARRIED, description, BIRTHDAY, REGISTERED_TIME, ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

这里也许看不出什么端倪来,现在在 session.save(customer) 后面加一行代码,输出这个 customer OID System.out.println(customer.getId()) ,再次运行程序,控制台输出为:

Hibernate: select max(ID) from CUSTOMER

22

Hibernate: insert into CUSTOMER (NAME, EMAIL, PASSWORD, PHONE, ADDRESS, SEX, IS_MARRIED, description, BIRTHDAY, REGISTERED_TIME, ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

OID insert 语句之前输出,这可以说明两个问题: 1.insert 语句并不是在执行 save 的时候发送给数据库的; 2.insert 语句是在执行 commit 的时候发送给数据库的。结合前面我们所说过的:执行 save 的时候, Hibernate 会首先把对象放入缓存,然后计划一条 insert 语句。一个基本的插入流程就出来了:

1.   判断所要保存的实例是否已处于持久化状态,如果不是,则将其置入缓存;

2.   根据所要保存的实例计划一条 insert sql 语句,注意只是计划,并不执行;

3.   事务提交时执行之前所计划的 insert 语句;

后台还打印出了 select max(ID) from CUSTOMER ,这主要是为了给 customer 赋予一个 OID ,因为一般情况下临时对象的 OID NULL

接着我们做两个测试:

1.   tx.commit(); 注释掉,此时控制台没有打印出 insert 语句;

2.   tx.commit() 换成 session.flush ,此时控制太打印出了 insert 语句,但是数据库中并没有添加新的记录;

通过查阅 Hibernate API 可以知道 flush 方法的主要作用就是清理缓存,强制数据库

Hibernate 缓存同步,以保证数据的一致性。它的主要动作就是向数据库发送一系列的 sql 语句,并执行这些 sql 语句,但是不会向数据库提交。而 commit 方法则会首先调用 flush 方法,然后提交事务。这就是为什么我们仅仅调用 flush 的时候记录并未插入到数据库中的原因,因为只有提交了事务,对数据库所做的更新才会被保存下来。因为 commit 方法隐式的调用了 flush ,所以一般我们都不会显示的调用 flush 方法。

     补充:mysql数据库默认情况下是自动提交事务的,也是说当你flush之后,数据已经被数据库自动提交了。

C:\Users\12524\.jdks\openjdk-24.0.1\bin\java.exe "-javaagent:C:\app\IDEA\IntelliJ IDEA 2025.1.3\lib\idea_rt.jar=52421" -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath C:\Users\12524\IdeaProjects\HibernateDemo\target\classes;C:\Users\12524\.m2\repository\org\hibernate\hibernate-core\5.6.10.Final\hibernate-core-5.6.10.Final.jar;C:\Users\12524\.m2\repository\org\jboss\logging\jboss-logging\3.4.3.Final\jboss-logging-3.4.3.Final.jar;C:\Users\12524\.m2\repository\javax\persistence\javax.persistence-api\2.2\javax.persistence-api-2.2.jar;C:\Users\12524\.m2\repository\net\bytebuddy\byte-buddy\1.12.9\byte-buddy-1.12.9.jar;C:\Users\12524\.m2\repository\antlr\antlr\2.7.7\antlr-2.7.7.jar;C:\Users\12524\.m2\repository\org\jboss\spec\javax\transaction\jboss-transaction-api_1.2_spec\1.1.1.Final\jboss-transaction-api_1.2_spec-1.1.1.Final.jar;C:\Users\12524\.m2\repository\org\jboss\jandex\2.4.2.Final\jandex-2.4.2.Final.jar;C:\Users\12524\.m2\repository\com\fasterxml\classmate\1.5.1\classmate-1.5.1.jar;C:\Users\12524\.m2\repository\javax\activation\javax.activation-api\1.2.0\javax.activation-api-1.2.0.jar;C:\Users\12524\.m2\repository\org\hibernate\common\hibernate-commons-annotations\5.1.2.Final\hibernate-commons-annotations-5.1.2.Final.jar;C:\Users\12524\.m2\repository\javax\xml\bind\jaxb-api\2.3.1\jaxb-api-2.3.1.jar;C:\Users\12524\.m2\repository\org\glassfish\jaxb\jaxb-runtime\2.3.1\jaxb-runtime-2.3.1.jar;C:\Users\12524\.m2\repository\org\glassfish\jaxb\txw2\2.3.1\txw2-2.3.1.jar;C:\Users\12524\.m2\repository\com\sun\istack\istack-commons-runtime\3.0.7\istack-commons-runtime-3.0.7.jar;C:\Users\12524\.m2\repository\org\jvnet\staxex\stax-ex\1.8\stax-ex-1.8.jar;C:\Users\12524\.m2\repository\com\sun\xml\fastinfoset\FastInfoset\1.2.15\FastInfoset-1.2.15.jar;C:\Users\12524\.m2\repository\com\mysql\mysql-connector-j\8.0.32\mysql-connector-j-8.0.32.jar;C:\Users\12524\.m2\repository\com\google\protobuf\protobuf-java\3.21.9\protobuf-java-3.21.9.jar com.example.Main 7月 09, 2025 9:46:43 上午 org.hibernate.Version logVersion INFO: HHH000412: Hibernate ORM core version 5.6.10.Final 7月 09, 2025 9:46:43 上午 org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit> INFO: HCANN000001: Hibernate Commons Annotations {5.1.2.Final} 7月 09, 2025 9:46:43 上午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!) 7月 09, 2025 9:46:43 上午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001005: using driver [com.mysql.cj.jdbc.Driver] at URL [jdbc:mysql://localhost:3306/test] 7月 09, 2025 9:46:43 上午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001001: Connection properties: {user=root, password=****} 7月 09, 2025 9:46:43 上午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001003: Autocommit mode: false 7月 09, 2025 9:46:43 上午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init> INFO: HHH000115: Hibernate connection pool size: 20 (min=1) 7月 09, 2025 9:46:44 上午 org.hibernate.dialect.Dialect <init> INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect 7月 09, 2025 9:46:44 上午 org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@5f254608] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode. 7月 09, 2025 9:46:44 上午 org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] Hibernate: insert into user (age, name) values (?, ?) User inserted successfully! 进程已结束,退出代码为 0
最新发布
07-10
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值