Hibernate的事务管理源码
User类:
- public class User implements Serializable{
- public User(){}
- private Integer id;
- private String name;
- private Integer age;
- private static final long serialVersionUID = 1L;
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Integer getAge() {
- return age;
- }
- public void setAge(Integer age) {
- this.age = age;
- }
- }
User.hbm.xml:
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
- <hibernate-mapping>
- <class name="com.po.User"
- table="TEST_USER">
- <id name="id" column="id" type="java.lang.Integer">
- <generator class="assigned"/>
- </id>
- <property name="name"
- column="name"
- type="java.lang.String"
- not-null="true"
- unique="true"
- length="20"/>
- <property name="age"
- column="age"
- type="java.lang.Integer"
- not-null="true"
- unique="false"
- length="0"/>
- </class>
- </hibernate-mapping>
hibernate.cfg.xml:
- <?xml version='1.0' encoding='utf-8'?>
- <!DOCTYPE hibernate-configuration PUBLIC
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
- <hibernate-configuration>
- <session-factory>
- <property name="show_sql">true</property>
- <property name="hibernate.connection.driver_class">
- oracle.jdbc.driver.OracleDriver
- </property>
- <property name="hibernate.connection.url">
- jdbc:oracle:thin:@192.168.58.1:1521:123
- </property>
- <property name="hibernate.connection.username">123</property>
- <property name="hibernate.connection.password">123</property>
- <property name="dialect">org.hibernate.dialect.OracleDialect</property>
- <mapping resource="com/po/User.hbm.xml"/>
- </session-factory>
- </hibernate-configuration>
测试类:
- public class Test {
- public static void main(String[] args) {
- User user = new User();
- user.setId(1);
- user.setName("111");
- user.setAge(10);
- Configuration conf = new Configuration().configure();
- SessionFactory sf = conf.buildSessionFactory();
- Session sess = sf.openSession();
- Transaction t = sess.beginTransaction();//说明一
- try{
- sess.save(user);
- t.commit();//说明二
- }catch(Exception e){
- t.rollback();
- }finally{
- if(sess.isOpen()){
- sess.close();
- }
- }
- }
- }
说明一:Hibernate本身没有实现自己的事务管理功能,而是对底层JDBC事务或JTA事务的轻量级封装
org.hibernate.impl.SessionImpl类(该类是会话的实现类):
- public Transaction beginTransaction() throws HibernateException {
- errorIfClosed();
- if ( rootSession != null ) {
- log.warn( "Transaction started on non-root session" );
- }
- Transaction result = getTransaction();
- result.begin();
- return result;
- }
- public Transaction getTransaction() throws HibernateException {
- errorIfClosed();
- return jdbcContext.getTransaction();
- }
org.hibernate.jdbc.JDBCContext类:
- public Transaction getTransaction() throws HibernateException {
- if (hibernateTransaction==null) {
- hibernateTransaction = owner.getFactory().getSettings()
- .getTransactionFactory().createTransaction( this, owner );
- }
- return hibernateTransaction;
- }
TransactionFactory有很多实现类:
选择最基本的org.hibernate.transaction.JDBCTransactionFactory观察一下:
- public Transaction createTransaction(JDBCContext jdbcContext, Context transactionContext)throws HibernateException {
- return new JDBCTransaction( jdbcContext, transactionContext );
- }
org.hibernate.transaction.JDBCTransaction类的说明:
- Transaction implementation based on transaction management through a JDBC Connection.
- This the Hibernate's default transaction strategy.
事务开始时,会禁用自动提交:
- public void begin() throws HibernateException {
- if (begun) {
- return;
- }
- if (commitFailed) {
- throw new TransactionException("cannot re-start transaction after failed commit");
- }
- log.debug("begin");
- try {
- toggleAutoCommit = jdbcContext.connection().getAutoCommit();
- if ( log.isDebugEnabled() ) {
- log.debug("current autocommit status: " + toggleAutoCommit);
- }
- if (toggleAutoCommit) {
- log.debug("disabling autocommit");
- jdbcContext.connection().setAutoCommit(false);//关闭事务自动提交
- }
- }
- catch (SQLException e) {
- log.error("JDBC begin failed", e);
- throw new TransactionException("JDBC begin failed: ", e);
- }
- callback = jdbcContext.registerCallbackIfNecessary();
- begun = true;
- committed = false;
- rolledBack = false;
- if ( timeout>0 ) {
- jdbcContext.getConnectionManager().getBatcher().setTransactionTimeout(timeout);
- }
- jdbcContext.afterTransactionBegin(this);
- }
打开log日志也能看出很多端倪:
- [2013-08-09 16:37:55] DEBUG -> begin
- [2013-08-09 16:37:55] DEBUG -> opening JDBC connection
- [2013-08-09 16:37:55] DEBUG -> current autocommit status: false
- [2013-08-09 16:37:55] DEBUG -> generated identifier: 1, using strategy: org.hibernate.id.Assigned
- [2013-08-09 16:37:55] DEBUG -> commit
说明二:不需要显式的调用flush()方法,事务提交时会根据session的FlushMode自动触发session的flush
还是通过最基本的JDBCTransaction类看一下:
事务提交完成之后又恢复了事务的自动提交
- public void commit() throws HibernateException {
- if (!begun) {
- throw new TransactionException("Transaction not successfully started");
- }
- log.debug("commit");
- if ( !transactionContext.isFlushModeNever() && callback ) {
- transactionContext.managedFlush(); //根据FlushMode(通常为AUTO)刷新Session
- notifySynchronizationsBeforeTransactionCompletion();
- if ( callback ) {
- jdbcContext.beforeTransactionCompletion( this );
- }
- try {
- commitAndResetAutoCommit();//在该方法中重新开启了事务自动提交
- log.debug("committed JDBC Connection");
- committed = true;
- if ( callback ) {
- jdbcContext.afterTransactionCompletion( true, this );
- }
- notifySynchronizationsAfterTransactionCompletion( Status.STATUS_COMMITTED );
- }
- catch (SQLException e) {
- log.error("JDBC commit failed", e);
- commitFailed = true;
- if ( callback ) {
- jdbcContext.afterTransactionCompletion( false, this );
- }
- notifySynchronizationsAfterTransactionCompletion( Status.STATUS_UNKNOWN );
- throw new TransactionException("JDBC commit failed", e);
- }
- finally {
- closeIfRequired();
- }
- }
- private void commitAndResetAutoCommit() throws SQLException {
- try {
- jdbcContext.connection().commit();
- }
- finally {
- toggleAutoCommit();
- }
- }
- private void toggleAutoCommit() {
- try {
- if (toggleAutoCommit) {
- log.debug("re-enabling autocommit");
- jdbcContext.connection().setAutoCommit( true );//重新开启事务自动提交
- }
- }
- catch (Exception sqle) {
- log.error("Could not toggle autocommit", sqle);
- //swallow it (the transaction _was_ successful or successfully rolled back)
- }
- }
JDBC事务默认自动提交,但是如果Hibernate的事务策略使用JDBC,在事务开始之前,Hibernate会关闭事务自动提交,在事务结束之后,重新开启事务自动提交

浙公网安备 33010602011771号