hibernate之二级缓存

来源:互联网 发布:变形金刚中的矩阵 编辑:程序博客网 时间:2024/05/16 01:06

在hibernate中session缓存作为一级缓存,是事务缓存;SessionFactory缓存是二级缓存,是hibernate管理的进程缓存


要使用二级缓存,首先要在hibernate.cfg.xml中进行二级缓存的配置信息

<!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="dialect">org.hibernate.dialect.MySQLDialect</property><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property><property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_example_01</property><property name="hibernate.connection.username">root</property><property name="hibernate.connection.password">123</property><property name="show_sql">true</property><property name="format_sql">false</property><property name="hbm2ddl.auto">update</property> <!-- <mapping resource="hibernate_a_helloword/User.hbm.xml" /> --> <!-- 设置默认的事务隔离级别:隔离级别对应的整数表示READ UNCOMMITED1READ COMMITED2REPEATABLE READ4SERIALIZEABLE8 --><property name="connection.isolation">2</property><!-- C3P0连接池设定--><!-- 使用c3p0连接池  配置连接池提供的供应商--><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><!-- 使用二级缓存,默认是未打开的。 --><!-- 指定要使用的缓存的提供商,这也就打开了二级缓存 <property name="cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>--><property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property><!-- 开启使用查询缓存 --><property name="cache.use_query_cache">true</property><!-- 指定要使用二级缓存的实体类 --><class-cache usage="read-write" class="hibernate_a_example.Employee"/><class-cache usage="read-write" class="hibernate_a_example.Department"/><collection-cache usage="read-write" collection="hibernate_a_example.Department.employees"/></session-factory></hibernate-configuration>

然后就可以在类实现二级缓存

package hibernate_a_example;import java.util.Iterator;import java.util.List;import org.hibernate.Hibernate;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;import org.junit.Test;public class App {private static SessionFactory sessionFactory = new Configuration()//.configure()//.addClass(Department.class)// 添加Hibernate实体类(加载对应的映射文件).addClass(Employee.class)// 添加Hibernate实体类(加载对应的映射文件).buildSessionFactory();// 测试一级缓存(Session缓存)@Testpublic void testSessionCache() throws Exception {// ===================== 第1个SessionSession session = sessionFactory.openSession();session.beginTransaction();Employee employee = (Employee) session.get(Employee.class, 1); // 获取session.getTransaction().commit();session.close();// ===================== 第2个SessionSession session2 = sessionFactory.openSession();session2.beginTransaction();Employee employee2 = (Employee) session2.get(Employee.class, 1); // 获取session2.getTransaction().commit();session2.close();}// 测试二级缓存@Testpublic void testSecondCache() throws Exception {// ===================== 第1个SessionSession session = sessionFactory.openSession();session.beginTransaction();Department department = (Department) session.get(Department.class, 1); // 获取System.out.println(department.getName());System.out.println(department.getEmployees());session.getTransaction().commit();session.close();// ===================== 第2个SessionSession session2 = sessionFactory.openSession();session2.beginTransaction();Department department2 = (Department) session2.get(Department.class, 1); // 获取System.out.println(department2.getName());System.out.println(department2.getEmployees());session2.getTransaction().commit();session2.close();}// 测试查询缓存// 当使用Query.list()时,默认不会使用二级缓存@Testpublic void testQueryCache() throws Exception {// ===================== 第1个SessionSession session = sessionFactory.openSession();session.beginTransaction();List<Employee> list = session.createQuery("FROM Employee e WHERE e.id<10").list();System.out.println(list);Employee employee5 = (Employee) session.get(Employee.class, 5);System.out.println(employee5);session.getTransaction().commit();session.close();// ===================== 第2个SessionSession session2 = sessionFactory.openSession();session2.beginTransaction();List<Employee> list2 = session2.createQuery("FROM Employee e WHERE e.id<10").list();System.out.println(list2);session2.getTransaction().commit();session2.close();}// 测试查询缓存// 在使用HQL方式的查询时,如果用iterate()方法,就会使用缓存。// 因为这个方法是先查询所有符合条件的id集合,再一个一个的按id查找数据,就能用上缓存了。// 但这个方法会有N+1次查询的问题,提升性能有限,不太常用。@Testpublic void testQueryCache2() throws Exception {// ===================== 第1个SessionSession session = sessionFactory.openSession();session.beginTransaction();Iterator<Employee> iterator = session.createQuery("FROM Employee e WHERE e.id<8").iterate();while (iterator.hasNext()) {Employee e = iterator.next();System.out.println(e);}Employee employee5 = (Employee) session.get(Employee.class, 5);System.out.println(employee5);session.getTransaction().commit();session.close();System.out.println("\n------------------\n");// ===================== 第2个SessionSession session2 = sessionFactory.openSession();session2.beginTransaction();Iterator<Employee> iterator2 = session2.createQuery("FROM Employee e WHERE e.id<10").iterate();while (iterator2.hasNext()) {Employee e = iterator2.next();System.out.println(e);}session2.getTransaction().commit();session2.close();}@Testpublic void testQueryCache3() throws Exception {// ===================== 第1个SessionSession session = sessionFactory.openSession();session.beginTransaction();List list = session.createQuery("FROM Employee e WHERE e.id<18")//.setCacheable(true)// 是否使用查询缓存,需要在hibernate.cfg.xml中开启查询缓存才行.list();System.out.println(list);session.getTransaction().commit();session.close();System.out.println("\n------------------\n");// ===================== 第2个SessionSession session2 = sessionFactory.openSession();session2.beginTransaction();List list2 = session2.createQuery("FROM Employee e WHERE e.id<18")//.setCacheable(true)// 是否使用查询缓存.list();System.out.println(list2);session2.getTransaction().commit();session2.close();}// 测试Update与 Delete格式的HQL语对二级缓存的影响// 会让二级缓存中相关的数据失效,下次使用这些数据时会重新到数据库中加载@Testpublic void testUpdateTimestampCache() throws Exception {// ===================== 第1个SessionSession session = sessionFactory.openSession();session.beginTransaction();// 先获取Employee employee = (Employee)session.get(Employee.class, 1);System.out.println(employee.getName());// 再直接更新DBsession.createQuery("UPDATE Employee e SET e.name=? WHERE id=?")//.setParameter(0, "测试")//.setParameter(1, 1)//.executeUpdate();// 执行// 再显示这个员工的名称System.out.println(employee.getName());session.getTransaction().commit();session.close();System.out.println("\n------------------\n");// ===================== 第2个SessionSession session2 = sessionFactory.openSession();session2.beginTransaction();Employee employee2 = (Employee)session2.get(Employee.class, 1);System.out.println(employee2.getName());session2.getTransaction().commit();session2.close();}}


在hibernate中有一个线程的session,使用的是getCurrentSession方法

要使用也是要在cfg.xml中配置绑定的线程信息

<!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 name="foo"><!-- 配置数据库信息 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property><property name="connection.url">jdbc:mysql:///hibernate_20120328</property><property name="connection.driver_class">com.mysql.jdbc.Driver</property><property name="connection.username">root</property><property name="hibernate.connection.password">root</property><!-- 其他配置 --><property name="hibernate.show_sql">true</property><property name="hibernate.format_sql">false</property><property name="hbm2ddl.auto">update</property><!-- 当配置为thread时,SessionFactory的getCurrentSession()方法就能使用了 --><property name="current_session_context_class">thread</property></session-factory></hibernate-configuration>

在类中实现

package hibernate_a_example;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;import org.junit.Test;public class App2 {private static SessionFactory sessionFactory = new Configuration()//.configure("hibernate_a_example/myhibernate.cfg.xml")//.buildSessionFactory();// 要想使用SessionFactory.getCurrentSession()方法// 需要在Hibernate主配置文件中配置current_session_context_class项。// getCurrentSession()方法:// >> 去指定的上下文中(如thread)查找绑定的Session对象,如果有就返回。// >> 如果没有,就创建一个并绑定好,然后返回// >> openSession()只是开启一个新的Session,不会做绑定和查找操作。@Testpublic void testSession() throws Exception {Session session1 = sessionFactory.getCurrentSession();Session session2 = sessionFactory.getCurrentSession();System.out.println(session1 != null); // trueSystem.out.println(session1 == session2); // true}// 当使用getCurrentSession时,Hibernate会在提交或回滚后自动的关闭Session@Testpublic void testSessionClose() throws Exception {Session session = sessionFactory.getCurrentSession();session.beginTransaction();System.out.println("使用Session做XXX操作");session.getTransaction().commit(); //session.close(); // 当使用getCurrentSession时,就不能再自己关闭了}@Testpublic void testSession2() throws Exception {Session session1 = sessionFactory.openSession();Session session2 = sessionFactory.openSession();System.out.println(session1 != null); // trueSystem.out.println(session1 == session2); // false}@Testpublic void testSession3() throws Exception {Session session2 = sessionFactory.getCurrentSession();Session session1 = sessionFactory.openSession();System.out.println(session1 != null); // trueSystem.out.println(session1 == session2); // false}}

在使用了二级缓存,session所要查询的对象在一个事务中是同一个事务,除非提交了事务或者关闭了事务,会产生另一个session对象,opensession产生的session对象每次产生的都是新的session,在一个事务中不是唯一

0 0
原创粉丝点击