hibernate的二级缓存操作及session的管理方法及数据的批量处理

一.Department

package cn.edu.sdut.hibernate.erjihuancun;

import java.util.HashSet;
import java.util.Set;


public class Department {
	
	private int id;
	private String name;
	private Set<Employee> emps = new HashSet<>();
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set<Employee> getEmps() {
		return emps;
	}
	public void setEmps(Set<Employee> emps) {
		this.emps = emps;
	}
	
	
}
二.Employee
package cn.edu.sdut.hibernate.erjihuancun;

public class Employee {
	
	private int id;
	private String name;
	private float salary;
	private String email;
	private Department dept;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public float getSalary() {
		return salary;
	}
	public void setSalary(float salary) {
		this.salary = salary;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public Department getDept() {
		return dept;
	}
	public void setDept(Department dept) {
		this.dept = dept;
	}
	public Employee(float salary, String email, Department dept) {
		super();
		this.salary = salary;
		this.email = email;
		this.dept = dept;
	}
	public Employee() {
		// TODO Auto-generated constructor stub
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + ", email=" + email + ", dept=" + dept
				+ "]";
	}
	
	
}

三.Department.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">
<!-- Generated 2016-11-3 17:12:04 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="cn.edu.sdut.hibernate.erjihuancun.Department" table="GG_DEPARTMENT">
        <id name="id" type="int">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <set name="emps" table="GG_EMPLOYEE" inverse="false" lazy="true">
            <key>
                <column name="DEPT_ID" />
            </key>
            <one-to-many class="cn.edu.sdut.hibernate.erjihuancun.Employee" />
        </set>
    </class>
</hibernate-mapping>

四.Employee.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">
<!-- Generated 2016-11-3 17:12:04 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="cn.edu.sdut.hibernate.erjihuancun.Employee" table="GG_EMPLOYEE">
    	<!-- 配置二级缓存<cache usage="read-write"/> -->
        <id name="id" type="int">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="salary" type="float">
            <column name="SALARY" />
        </property>
        <property name="email" type="java.lang.String">
            <column name="EMAIL" />
        </property>
        <many-to-one name="dept" class="cn.edu.sdut.hibernate.erjihuancun.Department">
            <column name="DEPT_ID" />
        </many-to-one>
    </class>
    
    
    <!-- 制定命名查询 -->
    <query name="hql"><![CDATA[from Employee e where e.salary > :sal and e.email like :email]]></query>
</hibernate-mapping>

五.HibernateUtils
package cn.edu.sdut.hibernate.hibernate;

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 HibernateUtils {
	
	//配置管理session的方法:
	//1.在hibernate.cfg.xml文件里配置
	//<!-- 配置管理 Session 的方式 --><property name="hibernate.current_session_context_class">thread</property>
	//2.主要用绑定当前线程的方法得到session,getSessionFactory().getCurrentSession();
	private HibernateUtils() {}

	private SessionFactory sessionFactory = null;
	private static HibernateUtils instance = new HibernateUtils();
	
	public static HibernateUtils getInstance(){
		return instance;
	}
	
	public SessionFactory getSessionFactory(){
		if (sessionFactory == null) {
			Configuration configuration = new Configuration().configure();
			ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
					.applySettings(configuration.getProperties())
					.buildServiceRegistry();
			sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		}
		return sessionFactory;
	}
	
	public Session getSession(){
		//getCurrentSession()将session与当前的线程绑定,如果当前线程没有session就会创建一个和线程绑定
		//否则继续调用与线程绑定的session
		return getSessionFactory().getCurrentSession();
	}
}
六.DepartmentDao

package cn.edu.sdut.hibernate.dao;

import org.hibernate.Session;

import cn.edu.sdut.hibernate.erjihuancun.Department;
import cn.edu.sdut.hibernate.hibernate.HibernateUtils;

public class DepartmentDao {

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

七.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>
    	
    	  
    	<!-- 配置连接数据库的基本信息 -->
    	<!-- 连接oracle数据库 -->
    	<property name="connection.username">scott</property>
    	<property name="connection.password">csc</property>
    	<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
    	<property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
    	
    	
    	<!-- 配置hibernate的基本信息 -->
    	<!-- hibernate 所使用的数据库方言 -->
    	<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
    	
    	<!-- 执行sql时是否在控制台上打印 -->
    	<property name="show_sql">true</property>
    	
    	<!-- 是否对sql进行格式化 -->
    	<property name="format_sql">true</property>
    	
    	<!-- 指定自动生成数据表的策略 -->
    	<property name="hbm2ddl.auto">update</property>
    	
    	<!-- 指定session的delete方法会把对象的id置为null -->
    	<property name="hibernate.use_identifier_rollback">true</property>
    	
    	<!-- 指定数据库的隔离级别 -->
    	<property name="connection.isolation">2</property>
    	
    	<!-- 设定JDBC的statment读取数据的时候每次在数据库中读取的记录的条数 -->
    	<property name="hibernate.jdbc.fetch_size">100</property>
    	<!-- 设定对数据进行批量操作,批次更新和批次插入的批次大小 -->
    	<property name="hibernate.jdbc.batch_size">30</property>
    	
    	<!-- 配置管理 Session 的方式 -->
    	<property name="hibernate.current_session_context_class">thread</property>
    	
    	<!-- 是否启用二级缓存 -->
    	<property name="cache.use_second_level_cache">true</property>
    	<!-- 启用查询缓存(二级缓存) -->
    	<property name="cache.use_query_cache">true</property>
    	<!-- 配置二级缓存用的缓存策略(也就是缓存用的插件) -->
    	<property name="hibernate.cache.region.factory_class">org.hibernate.cache.EhCacheRegionFactory</property>
    	
    	<!-- 指定关联的xxx.hbm.xml文件 -->
    	<!--  
    	<mapping resource="cn/edu/sdut/hibernate/hql/Department.hbm.xml"/>
    	<mapping resource="cn/edu/sdut/hibernate/hql/Employee.hbm.xml"/>
    	-->
    	
    	<mapping resource="cn/edu/sdut/hibernate/erjihuancun/Department.hbm.xml"/>
    	<mapping resource="cn/edu/sdut/hibernate/erjihuancun/Employee.hbm.xml"/>
    	
    	<class-cache usage="read-write" class="cn.edu.sdut.hibernate.erjihuancun.Employee"/>
    	<class-cache usage="read-write" class="cn.edu.sdut.hibernate.erjihuancun.Department"/>
    	<collection-cache usage="read-write" collection="cn.edu.sdut.hibernate.erjihuancun.Department.emps"/>
    </session-factory>
</hibernate-configuration>

八.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 -->
         
    <!--  
    	指定一个目录:当 EHCache 把数据写到硬盘上时, 将把数据写到这个目录下.此时将目录改为E:\cache
    --> 
    <diskStore path="E:\cache"/>


    <!--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 在不同的缓存区域保存不同的类/集合。
			对于类而言,区域的名称是类名。如:com.atguigu.domain.Customer
			对于集合而言,区域的名称是类名加属性名。如com.atguigu.domain.Customer.orders
   	-->
   	<!--  
   		name: 设置缓存的名字,它的取值为类的全限定名或类的集合的名字 
		maxElementsInMemory: 设置基于内存的缓存中可存放的对象最大数目 
		
		eternal: 设置对象是否为永久的, true表示永不过期,
		此时将忽略timeToIdleSeconds 和 timeToLiveSeconds属性; 默认值是false 
		timeToIdleSeconds:设置对象空闲最长时间,以秒为单位, 超过这个时间,对象过期。
		当对象过期时,EHCache会把它从缓存中清除。如果此值为0,表示对象可以无限期地处于空闲状态。 
		timeToLiveSeconds:设置对象生存最长时间,超过这个时间,对象过期。
		如果此值为0,表示对象可以无限期地存在于缓存中. 该属性值必须大于或等于 timeToIdleSeconds 属性值 
		
		overflowToDisk:设置基于内存的缓存中的对象数目达到上限后,是否把溢出的对象写到基于硬盘的缓存中 
	-->    
	<!-- 此时name改为只存放Department对象 -->
    <cache name="cn.edu.sdut.hibernate.erjihuancun.Department"
        maxElementsInMemory="1"
        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改为只存放Departemnt里面的emps集合 -->
    <cache name="cn.edu.sdut.hibernate.erjihuancun.Department.emps"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        /> -->

    <!-- Place configuration for your caches following -->

</ehcache>

九.Test

package cn.edu.sdut.hibernate.erjihuancun;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;


import cn.edu.sdut.hibernate.dao.DepartmentDao;
import cn.edu.sdut.hibernate.hibernate.HibernateUtils;

/**
 * 
 * 配置二级缓存的初始步骤:
 * 1.主要用的是ehcache-core-2.4.3.jar这个插件
 * 2.在项目里面加入hibernate-release-4.2.4.Final\lib\optional\ehcache下面的所有jar包
 * 3.在src里面配置ehcache.xml(可以在hibernate-release-4.2.4.Final\project\etc里面找到)
 *
 */


public class Test {

	private SessionFactory sessionFactory;
	private Session session;
	private Transaction transaction;
	
	@Before
	public void init(){
		Configuration configuration = new Configuration().configure();
		ServiceRegistry serviceRegistry = 
				new ServiceRegistryBuilder().applySettings(configuration.getProperties())
											.buildServiceRegistry();
		sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
	}
	
	@After
	public void destory(){
		transaction.commit();
		session.close();
		sessionFactory.close();
	}
	
	
	/**
	 * 进行批量处理的方法主要是JDBC 原生的 API 进行操作, 效率最高, 速度最快!
	 * session.doWork(new Work() {
	 *		@Override
	 *		public void execute(Connection arg0) throws SQLException {
	 *			//通过 JDBC 原生的 API 进行操作, 效率最高, 速度最快!
	 *		}
	 *	});
	 */
	@org.junit.Test
	public void testBatch(){
		session.doWork(new Work() {
			@Override
			public void execute(Connection arg0) throws SQLException {
				//通过 JDBC 原生的 API 进行操作, 效率最高, 速度最快!
			}
		});
	}
	
	@org.junit.Test
	public void testManageSession(){
		//获取 Session
		//开启事务
		Session session = HibernateUtils.getInstance().getSession();
		System.out.println("-->" + session.hashCode());
		Transaction transaction = session.beginTransaction();
		
		DepartmentDao departmentDao = new DepartmentDao();
		
		Department dept = new Department();
		dept.setName("ATGUIGU");
		
		departmentDao.save(dept);
		departmentDao.save(dept);
		departmentDao.save(dept);
		
		//若 Session 是由 thread 来管理的, 则在提交或回滚事务时, 已经关闭 Session 了,但sessionFactory没有关闭.
		//提交事务和回滚事务都会使session关闭
		transaction.commit();
		System.out.println(session.isOpen()); 
		//若session关闭之后再产生就会使是不同的对象
		System.out.println(HibernateUtils.getInstance().getSessionFactory().isClosed());
		session = HibernateUtils.getInstance().getSession();
		System.out.println("-->" + session.hashCode());
	}
	
	@org.junit.Test
	public void testQueryIterate(){
		Department dept = (Department) session.get(Department.class, 80);
		System.out.println(dept.getName());
		System.out.println(dept.getEmps().size()); 
		
		Query query = session.createQuery("FROM Employee e WHERE e.dept.id = 80");
		List<Employee> emps = query.list();
		System.out.println(emps.size()); 
		
		//前提是在一级缓存或二级缓存里面有你要查询的数据的情况下如果用Iterator会稍微提高一下性能,
		//否则将会降低查询效率
		//Iterator的查询原理是在一级缓存里面先查找,如果没有再从二级缓存里面查找,还没有就从数据库里面查找
		//尽量不要使用Iterator
		Iterator<Employee> empIt = query.iterate();
		while(empIt.hasNext()){
			System.out.println(empIt.next().getName()); 
		}
	}
	
	
	@org.junit.Test
	public void testUpdateTimeStampCache(){
		Query query = session.createQuery("FROM Employee");
		query.setCacheable(true);
		
		List<Employee> emps = query.list();
		System.out.println(emps.size());
		//修改属性后会根据时间戳缓存区域存放了对于查询结果相关的表进行插入, 更新或删除操作的时间戳. 
		Employee employee = (Employee) session.get(Employee.class, 100);
		employee.setSalary(30000);
		
		emps = query.list();
		System.out.println(emps.size());
	}
	
	@org.junit.Test
	public void testQueryCache(){
		//对于query和Criteria的缓存都是依赖于二级缓存的
		//设置缓存的方法:<!-- 启用查询缓存(二级缓存) -->
    	//				<property name="cache.use_query_cache">true</property>
		//		然后调用query.setCacheable(true);  criteria.setCacheable(true);
		Query query = session.createQuery("from Department");
		query.setCacheable(true);
		List<Department> list = query.list();
		System.out.println(list.size());
		list = query.list();
		System.out.println(list.size());
		
		Criteria criteria = session.createCriteria(Department.class);
		criteria.setCacheable(true);
		list = criteria.list();
		System.out.println(list.size());
		list = criteria.list();
		System.out.println(list.size());
	}
	
	
	@org.junit.Test
	public void testCollectionSecondLevelCache(){
		//配置集合的二级缓存:
		//配制方法:(1)在hibernate.cfg.xml文件里面配置
		//				①.<!-- 是否启用二级缓存 -->
		//		    	<property name="cache.use_second_level_cache">true</property>
		//		    	<!-- 配置二级缓存用的缓存策略(也就是缓存用的插件) -->
		//		    	<property name="hibernate.cache.region.factory_class">org.hibernate.cache.EhCacheRegionFactory</property>
		
		//				<class-cache usage="read-write" class="cn.edu.sdut.hibernate.erjihuancun.Employee"/>
		//		    	<class-cache usage="read-write" class="cn.edu.sdut.hibernate.erjihuancun.Department"/>
		//		    	<collection-cache usage="read-write" collection="cn.edu.sdut.hibernate.erjihuancun.Department.emps"/>
		//				方法一注意:切记把Employess也配置好二级缓存,否则只会把集合里面每个对象只初始化id,
		//							然后调用集合的时候会再一条一条去数据库查询,会降低查询效率。
		//				②.在Department和Employee的hbm.xml里面分别配置二级缓存属性,然后在set集合属性里面也配置二级缓存
		Department department = (Department) session.get(Department.class, 80);
		System.out.println(department.getName());
		System.out.println(department.getEmps().size());
		transaction.commit();
		session.close();
		
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
		Department department2 = (Department) session.get(Department.class, 80);
		System.out.println(department2.getName());
		System.out.println(department2.getEmps().size());
		
		
	}
	
	
	@org.junit.Test
	public void testHibernateSecondLevelCache(){
		//配置对象的二级缓存
		//配置方法:(1).在hibernate.cfg.xml文件里面配置
		//				①.<!-- 是否启用二级缓存 -->
		//		    	<property name="cache.use_second_level_cache">true</property>
		//		    	<!-- 配置二级缓存用的缓存策略(也就是缓存用的插件) -->
		//		    	<property name="hibernate.cache.region.factory_class">org.hibernate.cache.EhCacheRegionFactory</property>
		
		//				<class-cache usage="read-write" class="cn.edu.sdut.hibernate.erjihuancun.Employee"/>
		//				②.在Employee的hbm.xml文件里面配置	<cache usage="read-write"/>
		Employee employee = (Employee) session.get(Employee.class, 100);
		System.out.println(employee.getName());
		transaction.commit();
		session.close();
		
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
		Employee employee2 = (Employee) session.get(Employee.class, 100);
		System.out.println(employee2.getName());
		
	}
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值