Hibernate(十)
1.批处理
1 //批处理 :批量处理
2 //批量插入数据
3 @Test
4 public void addData(){
5 Random random=new Random();
6 for(int i=1;i<=100000000;i++){
7 Teacher teacher=new Teacher();
8 teacher.setTname(randomName());
9 //teacher : 持久化状态,持久化状态的对象是放在Session的一级缓存中,因为一级缓存是放在内存中.(1亿对象存放在内存中)
10 session.save(teacher);
11 // 当一级缓存中的对象达到一定数量,那就把一级缓存中的对象同步到底层的数据库,再清空一级缓存,释放内存
12 if(i%100==0){
13 //把一级缓存中的对象同步到底层的数据库.把session当中的数据刷到数据库,真正的保存
14 session.flush();
15 //清空一级缓存,释放内存
16 session.clear();
17 //如果写上边两句有问题,就加上下边两句
18 transaction.commit();
19 transaction = session.beginTransaction();
20 }
21 }
22 }
1 //批量修改
2 @Test
3 public void test6(){
4 for(int i=1;i<100000000;i++){
5 Teacher teacher = (Teacher) session.get(Teacher.class, i);
6 teacher.setTname(randomName());
7 session.update(teacher);
8 if(i%100==0){
9 session.flush();
10 session.clear();
11 transaction.commit();
12 transaction=session.beginTransaction();
13 }
14 }
15 }
1 //批量删除
2 @Test
3 public void test7(){
4 for(int i=1;i<100000000;i++){
5 Teacher teacher = (Teacher) session.get(Teacher.class, i);
6 session.delete(teacher);
7 if(i%100==0){
8 session.flush();
9 session.clear();
10 transaction.commit();
11 transaction=session.beginTransaction();
12 }
13 }
14 }
2.一级缓存Session
缓存的是对象
跟Session相关(存放在内存中).
默认是开启的.
作用:提高CUD操作的性能.
操作一级缓存的方法:
boolean contains(Object object)
判断Session的一级缓存中是否包含一个对象,包含的话这个对象就是持久化状态。
void evict(Object object)
从Session的一级缓存中逐出一个对象.(该对象就不是持久化状态的对象).
void flush()
将Session的一级缓存中的对象,同步到底层数据库表中.(立即同步)
void clear()
清空Session的一级缓存,所有的持久化状态的对象都清空。(释放内存)
void close()
关闭Session,先调用flush(),再调用clear().
1 @Test
2 public void test8(){
3 //list与iterate的区别
4
5 //1.list不读取缓存,但是查询结果放入缓存
6 Query query = session.createQuery("select t from Teacher t where t.tid<?");
7 List list = query.setParameter(0, 100).list();
8 System.out.println("========================");
9 //2.iterate 读取缓存
10 Query query2 = session.createQuery("select t from Teacher t where t.tid<?");
11 query2.setParameter(0, 100);
12 Iterator iterator = query2.iterate();
13 while(iterator.hasNext()){
14 System.out.println(iterator.next());
15 }
16 System.out.println("========================");
17 Iterator iterator1 = query2.iterate();
18 while(iterator1.hasNext()){
19 System.out.println(iterator1.next());
20 }
21 //3.get/load 都会查询缓存
22 Teacher teacher = (Teacher)session.get(Teacher.class, 100);
23 System.out.println(teacher.getTid()+teacher.getTname());
24 System.out.println("========================");
25 Teacher teacher1 = (Teacher)session.get(Teacher.class, 100);
26 System.out.println(teacher1.getTid()+teacher1.getTname());
27 System.out.println("========================");
28 Teacher teacher2 = (Teacher)session.load(Teacher.class, 100);
29 System.out.println(teacher2.getTid()+teacher2.getTname());
30 System.out.println("========================");
31 Teacher teacher3 = (Teacher)session.load(Teacher.class, 100);
32 System.out.println(teacher3.getTid()+teacher3.getTname());
33 }
3.二级缓存ehcache
缓存的是对象
跟SessionFactory相关,因为SessionFactory存活的时间长。
默认是关闭的.
作用:提高查询效率.
二级缓存中的对象存放到哪里,这个需要配置.
一般会配置内存中存放一些对象,超出了内存中放存的对象个数,就写入磁盘.
ehcache.xml (配置二级缓存对象存放的配置文件).
A.导包
B.开启二级缓存
hibernate.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>
C.从官方project示例中拷贝一个ehcache.xml文件到src目录底下
<ehcache>
<!-- diskStore: 配置二级缓存中的对象磁盘存储目录 -->
<diskStore path="C:\\ehcache"/>
<!-- 配置默认缓存区:
maxElementsInMemory : 配置二级缓存中的对象在内存中存放的最大数量.
eternal : 二级缓存中的对象是否永久有效。true: 永久有效、false: 不是永久有效.
timeToIdleSeconds : 配置二级缓存中的对象空闲的有效时间 120秒.
timeToLiveSeconds : 配置二级缓存中的对象存活的有效时间 120秒.
overflowToDisk : 配置二级缓存中的对象超出了内存中存放的最大数量,就写入磁盘.
-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<!-- 配置命名的缓存区 -->
<cache name="myCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
</ehcache>
D.配置哪些持久化类用二级缓存
方式一:在hibernate.cfg.xml配置
<!-- 配置持久化类用二级缓存 -->
<!-- region 不写就指定用ehcache.xml中的defaultCache,写了myCache就使用myCache名称的 -->
<class-cache usage="read-write" class="com.rong.entity.sql.Teacher" region="myCache"/>
方式二:在持久化类上
1 package com.rong.entity.sql; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 import javax.persistence.Entity; 7 import javax.persistence.FetchType; 8 import javax.persistence.GeneratedValue; 9 import javax.persistence.GenerationType; 10 import javax.persistence.Id; 11 import javax.persistence.OneToMany; 12 13 import org.hibernate.annotations.Cache; 14 import org.hibernate.annotations.CacheConcurrencyStrategy; 15 16 @Entity 17 @Cache(usage=CacheConcurrencyStrategy.READ_WRITE,region="myCache") 18 public class Teacher { 19 @Id 20 @GeneratedValue(strategy=GenerationType.AUTO) 21 private int tid; 22 private String tname; 23 @OneToMany(targetEntity=Student.class,fetch=FetchType.LAZY,mappedBy="teacher") 24 private Set<Student> students=new HashSet<Student>(); 25 public int getTid() { 26 return tid; 27 } 28 public void setTid(int tid) { 29 this.tid = tid; 30 } 31 public String getTname() { 32 return tname; 33 } 34 public void setTname(String tname) { 35 this.tname = tname; 36 } 37 public Set<Student> getStudents() { 38 return students; 39 } 40 public void setStudents(Set<Student> students) { 41 this.students = students; 42 } 43 }
E.代码查询
1 public static void main(String[] args) {
2 Configuration config = new Configuration().configure();
3 ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(config.getProperties())
4 .build();
5 SessionFactory factory = config.buildSessionFactory(serviceRegistry);
6 // 第一个session
7 Session session = factory.openSession();
8 Transaction transaction = session.beginTransaction();
9
10 Object object = session.get(Teacher.class, 1);
11 System.out.println(object);
12
13 Object object2 = session.get(Teacher.class, 2);
14 System.out.println(object2);
15
16 transaction.commit();
17 session.close();
18
19 // 第二个session
20 Session session1 = factory.openSession();
21 Transaction transaction1 = session1.beginTransaction();
22
23 Object object1 = session1.get(Teacher.class, 1);
24 System.out.println(object1);
25
26 transaction1.commit();
27 session1.close();
28
29 //看效果,休眠60秒
30 try {
31 Thread.sleep(1000*60);
32 } catch (InterruptedException e) {
33 e.printStackTrace();
34 }
35 factory.close();
36 }
生成缓存文件,但factory.close()执行后会删除该文件!!!
缓存操作
1 public static void main(String[] args) {
2 Configuration config = new Configuration().configure();
3 ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(config.getProperties())
4 .build();
5 SessionFactory factory = config.buildSessionFactory(serviceRegistry);
6 // 第一个session
7 Session session = factory.openSession();
8 Transaction transaction = session.beginTransaction();
9
10 Object object = session.get(Teacher.class, 1);
11 System.out.println(object);
12
13 Object object2 = session.get(Teacher.class, 2);
14 System.out.println(object2);
15
16 transaction.commit();
17 session.close();
18
19 // 第二个session
20 Session session1 = factory.openSession();
21 Transaction transaction1 = session1.beginTransaction();
22
23 Object object1 = session1.get(Teacher.class, 1);
24 System.out.println(object1);
25
26 transaction1.commit();
27 session1.close();
28
29
30
31 //获取缓存对象
32 Cache cache = factory.getCache();
33 //清空二级缓存中所有对象
34 // cache.evictAllRegions();
35 //从二级缓存中踢出指定的对象
36 // cache.evictEntity(Teacher.class, 1);
37 // cache.evictEntity("com.rong.entity.sql.Teacher", 1);
38 //从二级缓存中踢出指定类型所有的对象
39 // cache.evictEntityRegion(Teacher.class);
40 // cache.evictEntityRegion("com.rong.entity.sql.Teacher");
41 //判断二级缓存中在是否包含一个对象
42 boolean s1 = cache.containsEntity(Student.class, 1);
43 boolean s2 = cache.containsEntity("com.rong.entity.sql.Student", 1);
44 System.out.println(s1);
45 System.out.println(s2);
46
47 boolean t1 = cache.containsEntity(Teacher.class, 1);
48 boolean t2 = cache.containsEntity("com.rong.entity.sql.Teacher", 1);
49 System.out.println(t1);
50 System.out.println(t2);
51
52 factory.close();
53 }
获取统计信息
1.hibernate.cfg.xml配置
<!-- 配置生成二级缓存的统计信息 --> <property name="hibernate.generate_statistics">true</property> <!-- 让Hibernate4用更友好的方式格式化统计信息 --> <property name="hibernate.cache.use_structured_entries">true</property>
2.代码
1 public static void main(String[] args) { 2 Configuration config = new Configuration().configure(); 3 ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(config.getProperties()) 4 .build(); 5 SessionFactory factory = config.buildSessionFactory(serviceRegistry); 6 // 第一个session 7 Session session = factory.openSession(); 8 Transaction transaction = session.beginTransaction(); 9 10 Object object = session.get(Teacher.class, 1); 11 System.out.println(object); 12 13 Object object2 = session.get(Teacher.class, 2); 14 System.out.println(object2); 15 16 transaction.commit(); 17 session.close(); 18 19 // 第二个session 20 Session session1 = factory.openSession(); 21 Transaction transaction1 = session1.beginTransaction(); 22 23 Object object1 = session1.get(Teacher.class, 1); 24 System.out.println(object1); 25 26 transaction1.commit(); 27 session1.close(); 28 29 30 31 //获取缓存对象 32 Cache cache = factory.getCache(); 33 //清空二级缓存中所有对象 34 // cache.evictAllRegions(); 35 //从二级缓存中踢出指定的对象 36 // cache.evictEntity(Teacher.class, 1); 37 // cache.evictEntity("com.rong.entity.sql.Teacher", 1); 38 //从二级缓存中踢出指定类型所有的对象 39 // cache.evictEntityRegion(Teacher.class); 40 // cache.evictEntityRegion("com.rong.entity.sql.Teacher"); 41 //判断二级缓存中在是否包含一个对象 42 boolean s1 = cache.containsEntity(Student.class, 1); 43 boolean s2 = cache.containsEntity("com.rong.entity.sql.Student", 1); 44 System.out.println(s1); 45 System.out.println(s2); 46 47 boolean t1 = cache.containsEntity(Teacher.class, 1); 48 boolean t2 = cache.containsEntity("com.rong.entity.sql.Teacher", 1); 49 System.out.println(t1); 50 System.out.println(t2); 51 52 //获取统计信息 53 Statistics statistics = factory.getStatistics(); 54 //命中的数量 55 long secondLevelCacheHitCount = statistics.getSecondLevelCacheHitCount(); 56 System.out.println(secondLevelCacheHitCount);//1 57 //错失的数量 58 long secondLevelCacheMissCount = statistics.getSecondLevelCacheMissCount(); 59 System.out.println(secondLevelCacheMissCount);//2 60 //获取老师的二级缓存的统计信息 61 SecondLevelCacheStatistics scs = statistics.getSecondLevelCacheStatistics("com.rong.entity.sql.Teacher"); 62 System.out.println(scs.getEntries()); 63 64 factory.close(); 65 }
代码查询语句
1.注意配置
<!-- 配置开启查询缓存 --> <property name="hibernate.cache.use_query_cache">true</property>
把查询的结果放入缓存
1 List<Student> students = session.createQuery("select s from Student s join fetch s.teacher where s.age > ?") 2 .setParameter(0, 30) 3 .setCacheable(true) // 设置缓存查询语句 4 .list(); 5 6 7 List<Student> students = session.createQuery("select s from Student s join fetch s.teacher where s.age > ?") 8 .setParameter(0, 20) 9 .setCacheable(true) // 设置缓存查询语句 10 .list();
4.Session线程安全问题
如果是Hibernate3.1之前版本,它提供了HibernateUtil工具类可以获取当前线程相关的Session.
如果是Hibernate3.1之后版本,它提供了可配置的方式,让我们把Session配置成线程相关的Session.
A.在hibernate.cfg.xml中配置
<property name="hibernate.current_session_context_class">thread</property>
B.代码
1 public static void main(String[] args) {
2 Configuration config = new Configuration().configure();
3 ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(config.getProperties())
4 .build();
5 SessionFactory factory = config.buildSessionFactory(serviceRegistry);
6 // 第一个session
7 Session session = factory.getCurrentSession();
8 Transaction transaction = session.beginTransaction();
9
10 Object object = session.get(Teacher.class, 1);
11 System.out.println(object);
12
13 Object object2 = session.get(Teacher.class, 2);
14 System.out.println(object2);
15
16 transaction.commit();
17 //session.close();自动关闭,不用手动关闭
18 System.out.println(session);
19
20 // 第二个session
21 Session session1 = factory.getCurrentSession();
22 Transaction transaction1 = session1.beginTransaction();
23
24 Object object1 = session1.get(Teacher.class, 1);
25 System.out.println(object1);
26
27 transaction1.commit();
28 //session1.close();自动关闭,不用手动关闭
29 System.out.println(session1);
30
31 factory.close();
32 }