• Hibernate之管理session与批处理


    1. Hibernate 自身提供了三种管理Session对象的方法

    Session对象的生命周期与本地线程绑定
    –Session 对象的生命周期与JTA事务绑定
    –Hibernate 委托程序管理Session对象的生命周期

    2.Hibernate中Session管理方式的配置

    Hibernate的配置文件中,hibernate.current_session_context_class属性用于指定Session管理方式,可选值包括
    thread:Session 对象的生命周期与本地线程绑定
    jta*:Session 对象的生命周期与 JTA 事务绑定
    managed: Hibernate 委托程序来管理Session对象的生命周期

    3. Session 对象的生命周期与本地线程绑定

    A、如果把 Hibernate配置文件的hibernate.current_session_context_class属性值设为thread,Hibernate 就会按照与本地线程绑定的方式来管理 Session
    B、Hibernate 按以下规则把Session与本地线程绑定
          –当一个线程(threadA)第一次调用SessionFactory对象的getCurrentSession()方法时,该方法会创建一个新的Session(sessionA)对象,把该对象与threadA绑定,并将sessionA返回
         –当 threadA再次调用SessionFactory对象的getCurrentSession()方法时,该方法将返回sessionA对象
         –当 threadA提交sessionA对象关联的事务时,Hibernate 会自动flushsessionA对象的缓存,然后提交事务,关闭sessionA对象.当threadA撤销sessionA对象关联的事务时,也会自动关闭sessionA对象
         –若 threadA再次调用SessionFactory对象的getCurrentSession()方法时,该方法会又创建一个新的Session(sessionB)对象,把该对象与threadA绑定,并将sessionB返回
    C、Session对象的生命周期与本地线程绑定测试:

    首先,在hibernate配置文件中加入如下配置,用来生命session的管理方式:

     <!-- 配置管理session的方式 -->
        <property name="current_session_context_class">thread</property>
    

    再写一个HibernateUtil类来统一的获取session对象:

    public class HibernateUtil {
        
    	private SessionFactory sessionFactory;
    	
    	private static HibernateUtil instance=new HibernateUtil();
    	
    	private HibernateUtil(){};
    	
    	public static HibernateUtil getInstance(){
    		return instance;
    	}
    
    	public SessionFactory getSessionFactory() {
    		if(this.sessionFactory==null){		
    			Configuration cfg=new Configuration().configure();
    			ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
    			this.sessionFactory=cfg.buildSessionFactory(serviceRegistry);
    		}
    		return sessionFactory;
    	}
    	
    	public  Session getSession(){
    		return getSessionFactory().getCurrentSession();
    	}
    }
    提供一个DepartmentDao类用来操作Department数据:

    public class DepartmentDao {
       
    	public void save(Department dept){
    		Session session=HibernateUtil.getInstance().getSession();
    		System.out.println(session.hashCode());
    		//session.save(dept);
    	}
    }
    测试类:

    @Test
    	public void  testManagerSession(){
    		
    		Session session=HibernateUtil.getInstance().getSession();
    		Transaction transaction=session.beginTransaction();
    		Department dept=new Department();
    		dept.setName("abc");
    		DepartmentDao deptDao=new DepartmentDao();
    		deptDao.save(dept);
    		deptDao.save(dept);
    		deptDao.save(dept);
    		transaction.commit();
    		
    		//使用thread的方式管理session,则在提交和回滚事物时,关闭session
    		System.out.println(session.isOpen());
    	}
    测试结果:

    999807287
    999807287
    999807287
    false

    由此可见:在当前线程中,若没有执行提交事物或者回滚事物操作,通过getCurrentSession()方法获取到的都是同一个session对象,并且执行事物commit()之后,session关闭!

    4. 批处理数据

    A、批量处理数据是指在一个事务中处理大量数据.
    B、在应用层进行批量操作, 主要有以下方式:
          –通过 Session
          –通过 HQL
          –通过 StatelessSession
          –通过 JDBC API
    1. 通过session批处理数据:

    Session save()update()方法都会把处理的对象存放在自己的缓存中.如果通过一个Session对象来处理大量持久化对象,应该及时从缓存中清空已经处理完毕并且不会再访问的对象.具体的做法是在处理完一个对象或小批量对象后,立即调用flush() 方法刷新缓存, 然后在调用clear()方法清空缓存

    通过 Session来进行处理操作会受到以下约束

    需要在 Hibernate 配置文件中设置JDBC单次批量处理的数目,应保证每次向数据库发送的批量的SQL语句数目与batch_size属性一致

    若对象采用 “identity”标识符生成器,Hibernate无法在JDBC层进行批量插入操作

    进行批量操作时, 建议关闭Hibernate的二级缓存

    2. 通过HQL批处理:

    注意: HQL只支持INSERTINTO … SELECT形式的插入语句, 但不支持INSERTINTO … VALUES形式的插入语句. 所以使用HQL不能进行批量插入操作.
    3. 通过 StatelessSession

    从形式上看,StatelessSessionsession的用法类似。StatelessSessionsession相比,有以下区别:

    StatelessSession没有缓存,通过StatelessSession来加载、保存或更新后的对象处于游离状态。

    StatelessSession不会与Hibernate的第二级缓存交互。

    当调用StatelessSessionsave()、update()delete()方法时,这些方法会立即执行相应的SQL语句,而不会仅计划执行一条SQL语句

    StatelessSession不会进行脏检查,因此修改了Customer对象属性后,还需要调用StatelessSessionupdate()方法来更新数据库中数据。

    StatelessSession不会对关联的对象进行任何级联操作。

    通过同一个StatelessSession对象两次加载OID1Customer对象,得到的两个对象内存地址不同。

    StatelessSession所做的操作可以被Interceptor拦截器捕获到,但是会被Hibernate的事件处理系统忽略掉。

    4. 通过JDBC API(推荐)

    使用方式:

    public void testBatch(){
    		session.doWork(new Work() {
    			
    			@Override
    			public void execute(Connection con) throws SQLException {
    				//通过JDBC原生的API操作,效率最高,速度最快
    				
    			}
    		});
    	}



  • 相关阅读:
    0541-leetcode算法实现之反转字符串II-reverseStrII-python&golang实现
    helm 入门简介与安装(1)
    ubuntu18.04 netplan 设置dns,dns不生效
    服务器报错WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
    0344-leetcode算法实现之反转字符串-reverse-string-python&golang实现
    python os模块常用方法总结
    0076-leeycode算法实现之最小覆盖子串-minimum-window-substring-python&golang实现
    0904-leetcode算法实现之水果成篮-fruit-into-baskets-python&golang实现
    0209-leetcode算法实现之长度最小子数组-minimum-size-subarray-sum-python&golang实现
    0977-leetcode算法实现之有序数组的平方sqaure-of-a-sorted-array-python&golang实现
  • 原文地址:https://www.cnblogs.com/elgin-seth/p/5293749.html
Copyright © 2020-2023  润新知