day36 11-Hibernate中的事务:当前线程中的session

如果你没有同一个session开启事务的话,那它两是一个独立的事务。必须是同一个session才有效。它给我们提供一个本地线程的session。这个session就保证了你是同一个session。其实它底层用的就是ThreadLocal。

什么是JTA事务?就是你底层操作的时候可能操作的不是同一个数据库。我们这里的保存都往同一个数据库里面保存。user和person都是保存到mysql数据库那不叫JTA事务,如果user保存到mysql数据库,person保存到oracle数据库,那这种事务的绑定用的是JTA这种事务,就是你操作的都不是同一个数据库了。SessionFactory.getCurrentSession()直接把当前线程中的session给它拿回去就行。只要是同一个线程就行,同一个线程拿的session肯定是同一个。SessionFactory.getCurrentSession()拿到当前线程绑定的session。只要是一个线程里面得到的都是同一个session。只不过当前线程中的session得配置一个值<property name="hibernate.current_session_context_class">thread</property>才可以使用。

package cn.itcast.utils;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
 * Hibernate抽取工具类
 * @author 姜涛
 *
 */
public class HibernateUtils {
    private static Configuration configuration;
    private static SessionFactory sessionFactory;
    
    static{
        configuration = new Configuration().configure();
        sessionFactory = configuration.buildSessionFactory();
    }
    
    public static Session openSession(){
        return sessionFactory.openSession();
    }
    public static Session getCurrentSession(){
        return sessionFactory.getCurrentSession();//把当前线程中的session拿回去就行
    }
    public static void main(String[] args) {
        openSession();
    }
}
package cn.itcast.test;

import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.itcast.utils.HibernateUtils;
import cn.itcast.vo.Customer;


/**
 * 
 * Hibernate的事务管理:
 * @author zhongzh
 *
 */
public class HibernateDemo3 {
    @Test
    /*
     * 当前线程这个绑定的session的使用
     * 
     */
    public void demo8(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        Customer customer = new Customer();
        customer.setCname("张三");
        customer.setAge(28);
        session.save(customer);
        
        tx.commit();
        //session.close();
        
    }
    @Test
    /*
     * 事务通常在service层开启.session在DAO层.
     *   * 事务开启由session开启.
     * 
     */
    public void demo7(){//hibernate做的是dao层的代码
        Session session1 = HibernateUtils.openSession();
        Session session2 = HibernateUtils.openSession();
        System.out.println(session1==session2);
        Session session3 = HibernateUtils.getCurrentSession();
        Session session4 = HibernateUtils.getCurrentSession();
        System.out.println(session3 == session4);
    }
    @Test
    /*
     * 使用乐观锁解决丢失更新  也需要两个事务同时操作这条记录。
     */
      public void demo6(){
          Session session = HibernateUtils.openSession();
          Transaction tx = session.beginTransaction();
        
          Customer customer = (Customer) session.get(Customer.class, 3);
          customer.setAge(26);
          tx.commit();
          session.close();
      }
    @Test
    /*
     * 使用乐观锁解决丢失更新
     */
      public void demo5(){
          Session session = HibernateUtils.openSession();
          Transaction tx = session.beginTransaction();
        
          Customer customer =  (Customer) session.get(Customer.class, 3);
          customer.setCname("沈明贞");
          
          tx.commit();
          session.close();
      }
    @Test
    /*
     * 使用悲观锁解决丢失更新  底层执行的是同一个,只不过事务不一样而已
     */
      public void demo4(){
          Session session = HibernateUtils.openSession();
          Transaction tx = session.beginTransaction();
        // 使用悲观锁(排它锁)
            @SuppressWarnings("deprecation")
            Customer customer = (Customer) session.get(Customer.class, 3, LockMode.UPGRADE);
            customer.setAge(32);
          tx.commit();
          session.close();
      }
    @Test
    /*
     * 使用悲观锁解决丢失更新
     */
    public void demo3(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        // 使用悲观锁(排它锁)
        @SuppressWarnings("deprecation")
        Customer customer = (Customer) session.get(Customer.class, 3, LockMode.UPGRADE);
        customer.setCname("沈明贞");
        tx.commit();
        session.close();
    }
    
      @Test
      /*
       * 
       * 丢失更新的产生
       * 
       */
      public void demo2(){
          Session session = HibernateUtils.openSession();
          Transaction tx = session.beginTransaction();
          Customer customer =   (Customer) session.get(Customer.class, 3);
         //再有一个事务去更新customer的年龄
          customer.setAge(30);//持久态对象不用手动调update都可以完成更新
          
          //System.out.println(customer);
          tx.commit();
          session.close();
      }
  @Test
  /*
   * 
   * 丢失更新的产生
   * 
   */
  public void demo1(){
      Session session = HibernateUtils.openSession();
      Transaction tx = session.beginTransaction();
      Customer customer =   (Customer) session.get(Customer.class, 3);
      //假设就有一个事务在更新这个customer的名称
      customer.setCname("沈明贞");
      
      //System.out.println(customer);
      tx.commit();
      session.close();
  }
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
    <!-- 必须去配置的属性 -->
    <!-- 配置数据库连接的基本信息: -->
    <property name="hibernate.connection.driver_class">
        com.mysql.jdbc.Driver
    </property>
    <property name="hibernate.connection.url"><!-- 连接的数据库是hibernate3_day02 -->
        jdbc:mysql:///hibernate3_day03
    </property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password"></property>
    <!-- Hibernate的方言 -->
    <!-- 生成底层SQL不同的 -->
    <property name="hibernate.dialect">
        org.hibernate.dialect.MySQLDialect
    </property>

    <!-- 可选的属性 -->
    <!-- 显示SQL -->
    <property name="hibernate.show_sql">true</property>
    <!-- 格式化SQL -->
    <property name="hibernate.format_sql">true</property>

    <property name="hibernate.connection.autocommit">false</property>
    <!-- hbm:映射 to DDL: create drop alter -->
    <property name="hibernate.hbm2ddl.auto">update</property>

    <!-- C3P0连接池设定-->
    <!-- 使用c3po连接池  配置连接池提供的供应商-->
    <property name="connection.provider_class">
        org.hibernate.connection.C3P0ConnectionProvider
    </property>

    <!--在连接池中可用的数据库连接的最少数目 -->
    <property name="c3p0.min_size">5</property>
    <!--在连接池中所有数据库连接的最大数目  -->
    <property name="c3p0.max_size">20</property>
    <!--设定数据库连接的过期时间,以秒为单位,
        如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
    <property name="c3p0.timeout">120</property>
    <!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->
    <property name="c3p0.idle_test_period">3000</property>
    
    <!-- 
        1-Read uncommited isolation
        2-Read commmitted isolation   oracle默认是2
        4-Repeatable read isolation   mysql默认是4
        8-Serializable isolation
     -->
    <property name="hibernate.connection.isiolation">4</property>
    
    <!-- 通知Hibernate加载那些映射文件 -->
    <!--     <mapping resource="cn/itcast/hibernate3/demo1/Book.hbm.xml" />
        <mapping resource="cn/itcast/hibernate3/demo2/Customer.hbm.xml" />
        <mapping resource="cn/itcast/hibernate3/demo2/Order.hbm.xml" />
        <mapping resource="cn/itcast/hibernate3/demo1/Book.hbm.xml" /> -->
    <!-- 使用当前线程中的session -->
        <property name="hibernate.current_session_context_class">thread</property><!-- 代表了当前线程中的session -->
    <!-- 把映射文件中的这几个都拿掉  重新把它引入  -->
    <mapping resource="cn/itcast/vo/Customer.hbm.xml" />
    <mapping resource="cn/itcast/vo/Order.hbm.xml" />


</session-factory>
</hibernate-configuration>
原文地址:https://www.cnblogs.com/ZHONGZHENHUA/p/6703751.html