Hibernate的线程

Hibernate的线程

前提:由于后面学习的整合框架spring,是不能使用new 对象。所以不能使用构造函数传递session给DAO

想法:我们希望在DAO里面获得的Session对象和外层获得的Session的是同一个对象。不使用参数从外层调用方传递到DAO。

  • 如何实现外层的session和DAO的session是同一个对象?
  • 答:可以使用线程绑定。意思就是同一条线程的session对象是相同的。

线程绑定的作用:就是让同一条线程获得session对象是相同的,不需要参数传递session!!!!

所谓的线程绑定,就是使用一个线程变量将对象ThreadLoad保存起来,保证同一条线程获得同一个对象

所谓的绑定Session到当前线程,就是同一条线程的操作,session是相同的

实现的方式有两种:

  1. Hibernate的内置实现
  2. 自定义的ThreadLoad的线程变量实现。

不能同时配置


hibernate的内置实现

如果使用hibernate的内置实现要注意的事项:
1. session不能手动关闭

- session绑定到当前线程。会随线程启动而启动。随线程结束而结束。不能手工关闭

2. 所有的操作都要打开事务,包括查询(原来查询是不需要启动事务的)
- 配置了线程绑定,HIbernate就要验证事务激活状态,导致了所有的操作都要开启事务,包括查询!!

hibernate内置实现步骤:

  • 配置文件配置
 <!-- 绑定线程 -->
<property name="hibernate.current_session_context_class">thread</property>
  • 修改SessionFactory获得Session的代码,使用getCurrentSession()方法
//2.获得Session
public static Session getSession(){
    //前提是配置了sesion绑定当前线程
    //获得当前线程的session对象
    return sessionFactory.getCurrentSession();
}

内置实现后session不能手动关闭

@Test
public void save() {
    //如果外层的session和里面不一样,导致无法提交事务。
    //如果在不能使用参数将外层的session传递个DAO。要解决外层很DAO里面的session相同。
    //只能将session绑定到当前线程。只有在当前线程。我们获得的session是相同的
    Session session = HibernateUtils.getSession();
    System.out.println(session.hashCode()+"---");

    Transaction transaction = session.beginTransaction();

    CustomerDAO dao = new CustomerDAO();
    Customer c = new Customer();
    c.setCustName("百度");
    dao.save(c);

    transaction.commit();
    //如果session绑定到当前线程。会随线程启动而启动。随线程结束而结束。不能手工关闭
    //session.close();
}

所有的操作都要打开事务,包括查询(原来查询是不需要启动事务的)

@Test
public void get(){
    try {
        Session session = HibernateUtils.getSession();
        //如果使用了线程绑定,操作必须要启动事务。包括查询
         session.beginTransaction();
        Customer customer = session.get(Customer.class, 5L);
        System.out.println(customer.getCustName());
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

使用ThreadLoad自定义实现

  • 修改SessionFactory获得Session的代码,使用openSession()方法

使用ThreadLocal不用担心查询操作也要开启事务
修改工具类

public class HibernateUtils {


    public static final SessionFactory sessionFactory=HibernateUtils.createSessionFactory();
    //1.声明一个线程变量对象,所谓的线程变量,就是如果放在该变量里面的对象可以保持同一条线程共享。
    //2.如果将session放在threadLocal对象里面就可以实现同一条线程共享
    private static ThreadLocal<Session> threadLocal=new ThreadLocal<Session>();

    //获得会话工厂
    private static SessionFactory createSessionFactory(){
        //1.获得配置类对象Configuration
        Configuration config=new Configuration();
        //2.读取默认的配置文件(classpath:hibernate.cfg.xml)
        config.configure();
        //3.构建会话工厂
        SessionFactory sessionFactory = config.buildSessionFactory();

        return sessionFactory;
    }

    //2.获得一个会话,操作对象,通过threadLocal获得
    public static Session getSession(){
        //如果threadLocal没有值,那么就创建一个session对象放到里面
        if(threadLocal.get()==null){

            Session session = sessionFactory.openSession();
            threadLocal.set(session);
        }
        //如果threadLocal已经有对象了,就直接返回该session对象
      return threadLocal.get();
    }

    //注意:如果使用自定义的threadLocal绑定session到当前线程。直接使用session关闭了数据库连接,threadLocal里面的
    //session对象还在。就会导致下次获得的session的对象无法连接数据库。
    //所以,关闭了session还需要移除threadLocal里面的session
    public static void close(){
        //判断线程变量里面是否有session对象
        if(threadLocal.get()!=null){
            //如果有就获得session对象
            Session session = threadLocal.get();
            //关闭session对象
            session.close();
            //移除session对象
            threadLocal.remove();
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值