二级缓存&批量处理&管理session

二级缓存

package helloworld;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestHello {
	
	private SessionFactory sessionFactory;
	private Session sess;
	private Transaction trans;
	
	@Before
	public void before(){
		Configuration configuration = new Configuration().configure();
		ServiceRegistry registry = new ServiceRegistryBuilder()
										.applySettings(configuration.getProperties())
										.buildServiceRegistry();
		sessionFactory = configuration.buildSessionFactory(registry);
		sess = sessionFactory.openSession();
		trans = sess.beginTransaction();
	}
	
	@After
	public void after(){
		trans.commit();
		sess.close();
		sessionFactory.close();
	}
	/**1,二级缓存使用方法(helloworld)
	 * 导入对应的ehcache的jar包
	 * 写ehcache.xml
	 * 在cfg.xml中配置(三条)
	 * <property name="hibernate.cache.use_second_level_cache">true</property>
	 * <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
	 * <class-cache usage="read-write" class="helloworld.Employee"/><!-- 这条也可以在对应hbm.xml中配置<cache usage="read-write"/> -->
	 * 
	 * 
	 * 类级别的缓存
	 * */
	@Test
	public void testSecondCache() {
		Employee e = (Employee) sess.get(Employee.class, 2);
		System.out.println(e.getName());
		
		trans.commit();
		sess.close();
		sess = sessionFactory.openSession();
		trans = sess.beginTransaction();
		
		Employee e2 = (Employee) sess.get(Employee.class, 2);
		System.out.println(e2.getName());
	}
	
	/**
	 * 集合级别的缓存(需要建立在集合中的元素的类在二级缓存中的前提上,否则只是缓存了对应的id,会多出n多条查询)
	 * 
	 * */
	@Test
	public void testCollectionCache() {
		Department d = (Department) sess.get(Department.class, 1);
		System.out.println(d.getSet().size());
		
		trans.commit();
		sess.close();
		sess = sessionFactory.openSession();
		trans = sess.beginTransaction();
		
		Department d2 = (Department) sess.get(Department.class, 1);
		System.out.println(d2.getSet().size());
	}
	
	/**
	 * 查询缓存
	 * 默认情况下, 设置的缓存对 HQL 及 QBC 查询时无效的, 但可以通过以下方式使其是有效的

		I.  在 hibernate 配置文件中声明开启查询缓存

		<property name="cache.use_query_cache">true</property>

		II. 调用 Query 或 Criteria 的 setCacheable(true) 方法

		III. 查询缓存依赖于二级缓存
	 * */
	@Test
	public void testQueryCache() {
		
	}
	/**
	 * 时间戳缓存
	 * */
	
	
	
	/**
	 * Query 接口的 iterate() 方法
	 * */
}

ehcache.xml

<ehcache>

    <!-- Sets the path to the directory where cache .data files are created.

         If the path is a Java System Property it is replaced by
         its value in the running VM.

         The following properties are translated:
         user.home - User's home directory
         user.dir - User's current working directory
         java.io.tmpdir - Default temp file path -->
    <!-- 当二级缓存需要存放在硬盘上时,在硬盘上存放的位置
    	 当sessionFactory关闭是硬盘上的缓存也会删除	
     -->
    <diskStore path="D:/temp"/>


    <!--Default Cache configuration. These will applied to caches programmatically created through
        the CacheManager.

        The following attributes are required for defaultCache:

        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->
    <!-- 设置缓存的 默认 数据过期策略  -->
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />

    <!--Predefined caches.  Add your cache configuration settings here.
        If you do not have a configuration for your cache a WARNING will be issued when the
        CacheManager starts

        The following attributes are required for defaultCache:

        name              - Sets the name of the cache. This is used to identify the cache. It must be unique.
        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->

    <!-- Sample cache named sampleCache1
        This cache contains a maximum in memory of 10000 elements, and will expire
        an element if it is idle for more than 5 minutes and lives for more than
        10 minutes.

        If there are more than 10000 elements it will overflow to the
        disk cache, which in this configuration will go to wherever java.io.tmp is
        defined on your system. On a standard Linux system this will be /tmp"
        -->
    <!-- 
    	设定具体的命名缓存的数据过期策略。
    	每个命名缓存 代表一个缓存区域
    	
    	缓存区域(region):一个具有名称的缓存块,可以给每一个缓存块设置不同的缓存策略。
    						如果没有设置任何的缓存区域,则所有被缓存的对象,都将使用默认的缓存策略。
    						即:<defaultCache.../>
		Hibernate在不同的缓存区域保存不同的类/集合。
			对于类而言,区域的名称是类名。如:helloworld.Department
			对于集合而言,区域的名称是类名加属性名。如:helloworld.Department.set
    	
     -->
    <cache name="helloworld.Department"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />

    <!-- Sample cache named sampleCache2
        This cache contains 1000 elements. Elements will always be held in memory.
        They are not expired. -->
        
    <!--name 设置缓存的名字,它的取值为类的全限定名或类的集合的名字  -->
    <!--maxElementsInMemory 在内存中可以存放的最大条数 -->
    <!--eternal 设置对象是否为永久的,true表示永不过期,此时将忽略timeToIdleSeconds 和 timeToLiveSeconds属性; 默认值是false  -->
    <!--timeToIdleSeconds 设置对象空闲最长时间,以秒为单位, 超过这个时间,对象过期。当对象过期时,EHCache会把它从缓存中清除。如果此值为0,表示对象可以无限期地处于空闲状态。  -->
    <!--timeToLiveSeconds 设置对象生存最长时间,超过这个时间,对象过期。如果此值为0,表示对象可以无限期地存在于缓存中. 该属性值必须大于或等于 timeToIdleSeconds 属性值 -->
    <!--overflowToDisk 设置基于内存的缓存中的对象数目达到上限后,是否把溢出的对象写到基于硬盘的缓存中  -->
   
        
    <cache name="helloworld.Department.set"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        />

	 <cache name="helloworld.Employee"
        maxElementsInMemory="1"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />
    <!-- Place configuration for your caches following -->

</ehcache>

管理session

HibernateUtil

package manageSession;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

public class HibernateUtil {
	private HibernateUtil() {
	}

	private static HibernateUtil instance = new HibernateUtil();

	public static HibernateUtil getInstance() {
		return instance;
	}

	private SessionFactory sessionFactory;

	public SessionFactory getSessionFactory() {
		if (sessionFactory == null) {
			Configuration configuration = new Configuration().configure();
			ServiceRegistry registry = new ServiceRegistryBuilder()
					.applySettings(configuration.getProperties())
					.buildServiceRegistry();
			sessionFactory = configuration.buildSessionFactory(registry);
		}
		return sessionFactory;
	}
	public Session getSession(){
		return instance.getSessionFactory().getCurrentSession();
	}
}

EmployeeDao

package manageSession;

import org.hibernate.Session;

import helloworld.Employee;

public class EmployeeDao {
	/**
	 * 内部获取 Session 对象
	 * 获取和当前线程绑定的 Session 对象
	 * 1. 不需要从外部传入 Session 对象
	 * 2. 多个 DAO 方法也可以使用一个事务!
	 * */
	public void save(Employee emp){
		Session session = HibernateUtil.getInstance().getSession();
		System.out.println(session.hashCode());
		
		session.save(emp);
	}
}

TestManageSession

package manageSession;

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

import helloworld.Department;
import helloworld.Employee;

public class TestManageSession {

	@Test
	public void test() {
		Session session = HibernateUtil.getInstance().getSession();
		System.out.println("##"+session.hashCode());
		Transaction transaction = session.beginTransaction();
		
		EmployeeDao dao = new EmployeeDao();
		
		Employee e = new Employee();
		Department dep = new Department();
		dep.setId(1);
		e.setDepartment(dep);
		e.setName("jyf");
		e.setSalary(50000);
		
		dao.save(e);
		dao.save(e);
		dao.save(e);
		
		//若 Session 是由 thread 来管理的, 则在提交或回滚事务时, 已经关闭 Session 了. 
		System.out.println(session.isOpen());
		transaction.commit();
		System.out.println(session.isOpen());
	}

}

cfg.xml

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

批量处理(建议使用原生的connection进行)

package batch;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestBatch {

	private SessionFactory sessionFactory;
	private Session sess;
	private Transaction trans;

	@Before
	public void before() {
		Configuration configuration = new Configuration().configure();
		ServiceRegistry registry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
				.buildServiceRegistry();
		sessionFactory = configuration.buildSessionFactory(registry);
		sess = sessionFactory.openSession();
		trans = sess.beginTransaction();
	}

	@After
	public void after() {
		trans.commit();
		sess.close();
		sessionFactory.close();
	}

	/**
	 * 
	 * 
	 * */
	@Test
	public void testBatch() {
		sess.doWork(new Work() {
			// 最推荐使用原生的JDBC进行批量操作
			@Override
			public void execute(Connection connection) throws SQLException {
				PreparedStatement preparedStatement = connection
						.prepareStatement("insert into EMPLOYEES (SALARY, NAME, DEPARTMENT_ID)  values (?, ?, ?)");
				preparedStatement.setInt(1, 1);
				preparedStatement.setString(2, "JI_BATCH");
				preparedStatement.setInt(3, 1);
				preparedStatement.addBatch();
				preparedStatement.setInt(1, 2);
				preparedStatement.setString(2, "YUN_BATCH");
				preparedStatement.setInt(3, 2);
				preparedStatement.addBatch();
				preparedStatement.setInt(1, 3);
				preparedStatement.setString(2, "FEI_BATCH");
				preparedStatement.setInt(3, 1);
				preparedStatement.addBatch();
				preparedStatement.executeBatch();
			}
		});
	}
}

  

  

  

  

  

  

  

原文地址:https://www.cnblogs.com/feifeiyun/p/6485492.html