1.延迟加载(懒加载)
概念
需要用到该数据的时候才要加载
种类
类的延迟加载
案例
说明:注意:使用的是Load方法
1、 执行22行代码的时候,不发出sql语句,说明类的延迟加载和主键没有关系
2、 执行23行代码的时候,发出sql语句,说明只有在得到具体属性的时候才要发出sql语句。
3、 Session.load方法返回的对象是
而该对象是由javassist的jar包生成的,从代码结构可以看出该代理对象是持久化类的子类。
4、 在Classes.hbm.xml文件中
Lazy的属性默认为true
5、如果把上述的lazy改成false,则类的延迟加载不起作用了,默认为延迟加载。
集合的延迟加载
案例1
值说明
默认情况是true,当遍历集合的时候发出sql语句
Lazy的值为false,当加载classes的时候就把student加载出来了
Extra是更进一步的延迟加载策略,如果求大小、平均数、和等
案例2
案例3
当执行到上述的student.size()的时候,发出了如下的sql语句:
该sql语句只加载了大小,并没有加载具体的数据
Many-to-one的延迟加载
No-proxy 延迟加载 默认值
Proxy是加强版的延迟加载
因为是通过多的一方加载一的一方,所以对效率影响不大,所以一般情况下用默认值即可。
总结
延迟加载是通过什么时候发出sql语句来优化性能的。
1 <?xml version="1.0" encoding="utf-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <hibernate-mapping> 5 <class name="com.itheima09.hibernate.domain.Classes" lazy="true"> 6 <id name="cid" length="5"> 7 <generator class="increment"></generator> 8 </id> 9 <property name="name" length="20"></property> 10 <property name="description" length="100"></property> 11 <!-- 12 fetch 抓取策略 13 join 通过做外链接 14 select 默认值 15 subselect 16 --> 17 <set name="students" cascade="all" fetch="subselect" lazy="extra"> 18 <!-- 19 key代表外键 20 用来关联classes表和student表,用于在hibernate低层生成sql语句 21 --> 22 <key> 23 <column name="cid"></column> 24 </key> 25 <!-- 26 建立类与类之间的关联,用于客户端的编码 27 --> 28 <one-to-many class="com.itheima09.hibernate.domain.Student"/> 29 </set> 30 </class> 31 </hibernate-mapping>
1 package com.itheima09.hibernate.domain; 2 3 import java.io.Serializable; 4 import java.util.Set; 5 6 public class Classes implements Serializable{ 7 private Long cid; 8 private String name; 9 private String description; 10 private Set<Student> students; 11 public Long getCid() { 12 return cid; 13 } 14 public void setCid(Long cid) { 15 this.cid = cid; 16 } 17 public String getName() { 18 return name; 19 } 20 public void setName(String name) { 21 this.name = name; 22 } 23 public String getDescription() { 24 return description; 25 } 26 public void setDescription(String description) { 27 this.description = description; 28 } 29 public Set<Student> getStudents() { 30 return students; 31 } 32 public void setStudents(Set<Student> students) { 33 this.students = students; 34 } 35 }
1 <?xml version="1.0" encoding="utf-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <hibernate-mapping> 5 <class name="com.itheima09.hibernate.domain.Student"> 6 <id name="sid" length="5"> 7 <generator class="increment"></generator> 8 </id> 9 <property name="name" length="20"></property> 10 <property name="description" length="100"></property> 11 <!-- 12 column 为外键 13 --> 14 <many-to-one name="classes" column="cid" 15 class="com.itheima09.hibernate.domain.Classes" cascade="save-update" lazy="false"> 16 </many-to-one> 17 </class> 18 </hibernate-mapping>
1 import java.io.Serializable; 2 3 public class Student implements Serializable{ 4 private Long sid; 5 private String name; 6 private String description; 7 private Classes classes; 8 9 public Classes getClasses() { 10 return classes; 11 } 12 public void setClasses(Classes classes) { 13 this.classes = classes; 14 } 15 public Long getSid() { 16 return sid; 17 } 18 public void setSid(Long sid) { 19 this.sid = sid; 20 } 21 public String getName() { 22 return name; 23 } 24 public void setName(String name) { 25 this.name = name; 26 } 27 public String getDescription() { 28 return description; 29 } 30 public void setDescription(String description) { 31 this.description = description; 32 } 33 }
1 package com.itheima09.hibernate.lazy; 2 3 import java.util.List; 4 import java.util.Set; 5 6 import org.hibernate.Session; 7 import org.hibernate.Transaction; 8 import org.junit.Test; 9 10 import com.itheima09.hibernate.domain.Classes; 11 import com.itheima09.hibernate.domain.Student; 12 import com.itheima09.hibernate.utils.HibernateUtils; 13 14 public class LazyTest extends HibernateUtils{ 15 /** 16 * 类的延迟加载 17 */ 18 @Test 19 public void testload(){ 20 Session session = sessionFactory.openSession(); 21 Classes classes = (Classes)session.load(Classes.class, 1L); 22 System.out.println(classes.getCid());//不发出sql 23 session.close(); 24 System.out.println(classes.getName());//发出sql 25 } 26 27 @Test 28 public void testSet(){ 29 Session session = sessionFactory.openSession(); 30 Classes classes = (Classes)session.get(Classes.class, 1L); 31 Set<Student> students = classes.getStudents(); 32 for(Student student:students){ 33 System.out.println(student.getName()); 34 } 35 } 36 37 @Test 38 public void testSet_Extra(){ 39 Session session = sessionFactory.openSession(); 40 Classes classes = (Classes)session.get(Classes.class, 1L); 41 Set<Student> students = classes.getStudents(); 42 System.out.println(students.size()); 43 session.close(); 44 } 45 }
1 import org.hibernate.SessionFactory; 2 import org.hibernate.cfg.Configuration; 3 4 public class HibernateUtils { 5 public static SessionFactory sessionFactory; 6 static{ 7 Configuration configuration = new Configuration(); 8 configuration.configure(); 9 sessionFactory = configuration.buildSessionFactory(); 10 } 11 }
抓取策略和延迟加载的结合
研究对象
Set集合
1、 当fetch为join时,lazy失效
2、 当fetch为select时
如果lazy为true/extra
当遍历集合的时候,发出加载集合的sql语句
如果lazy为false
当获取班级的时候,发出加载集合的sql语句
3、 当fetch为subselect时和上面的情况一致。
二级缓存
概念
1、 是sessionFactory级别的缓存
2、 存放的是公有数据:共享数据
3、 二级缓存的生命周期是随着hibernate容器启动就开了,hibernate销毁,结束。
4、 Hibernate本身对二级缓存没有提供实现,是借助第三方插件实现的。
特点
公有数据的特征:
1、 一般情况下保持不变
2、 所有的人都能访问
3、 访问的频率比较高
4、 安全性不是特别高的数据
配置(重点)
1、 在hibernate的配置文件中
2、二级缓存分为类的二级缓存和集合的二级缓存
3、开启classes类的二级缓存
案例1
说明:
当第二次执行session.get方法的时候,并没有发出sql语句
案例2
说明:session.save方法不进二级缓存
案例3
说明:
Update方法不能让一个对象进入到二级缓存中。
案例4
说明:
执行55行代码的时候,把classes表中的所有的对象进入到了二级缓存中
执行59行代码的时候,重新从数据库中查找记录
所以createQuery(hql).list方法能把一个对象放入到二级缓存中,但是不利用二级缓存获取对象。
案例5
在classpath的根目录下放置一个ehcache.xml文件
从上述的配置可以看出,classes对象在内存中存放的数量最多为5个,多余的对象将存在磁盘上。
查找classes表中所有的对象,在内存中放置5个对象,剩余的对象将被存在磁盘上。
案例6
相当于开启了classes类中的set集合的二级缓存
把集合放入到了二级缓存中。
读写策略
Usage
Ready-only
只能把一个对象放入到二级缓存中不能修改
Read-write
能把一个对象放入到二级缓存中,也能修改
1 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> 3 4 <diskStore path="e:\TEMP1"/> 5 <defaultCache 6 maxElementsInMemory="12" 7 eternal="false" 8 timeToIdleSeconds="1200" 9 timeToLiveSeconds="1200" 10 overflowToDisk="false" 11 maxElementsOnDisk="10000000" 12 diskPersistent="false" 13 diskExpiryThreadIntervalSeconds="120" 14 memoryStoreEvictionPolicy="LRU" 15 /> 16 17 <Cache 18 name="com.itheima09.hibernate.domain.Classes" 19 maxElementsInMemory="5" 20 eternal="false" 21 timeToIdleSeconds="120" 22 timeToLiveSeconds="120" 23 overflowToDisk="true" 24 maxElementsOnDisk="10000000" 25 diskPersistent="false" 26 diskExpiryThreadIntervalSeconds="120" 27 memoryStoreEvictionPolicy="LRU" 28 /> 29 </ehcache>
1 <?xml version='1.0' encoding='utf-8'?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 5 <hibernate-configuration> 6 <!-- 7 一个session-factory代表一个数据库 8 --> 9 <session-factory> 10 <!-- 11 链接数据库的用户名 12 --> 13 <property name="connection.username">root</property> 14 <!-- 15 链接数据库的密码 16 --> 17 <property name="connection.password">root</property> 18 <!-- 19 链接数据库的驱动 20 --> 21 <property name="connection.driver_class"> 22 com.mysql.jdbc.Driver 23 </property> 24 <!-- 25 链接数据库的url 26 --> 27 <property name="connection.url"> 28 jdbc:mysql://localhost:3306/itheima09_hibernate 29 </property> 30 <!-- 31 方言 32 告诉hibernate用什么样的数据库 33 --> 34 <property name="dialect"> 35 org.hibernate.dialect.MySQLDialect 36 </property> 37 <!-- 38 validate 加载hibernate时,验证数据库的结构 39 update 加载hibernate时,检查数据库,如果表不存在,则创建,如果存在,则更新 40 create 每次加载hiberante,都会创建表 41 create-drop 每次加载hiberante,创建,卸载hiberante时,销毁 42 --> 43 <property name="hbm2ddl.auto">update</property> 44 <!-- 45 显示sql语句 46 --> 47 <property name="show_sql">true</property> 48 <!-- 49 格式化sql语句 50 --> 51 <property name="format_sql">true</property> 52 <!-- 53 session要从当前线程中产生 54 --> 55 <property name="current_session_context_class">thread</property> 56 <!-- 57 开启二级缓存 58 --> 59 <property name="cache.use_second_level_cache">true</property> 60 <!-- 61 二级缓存的供应商 62 --> 63 <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property> 64 <!-- 65 开启hibernate的统计机制 66 --> 67 <property name="hibernate.generate_statistics">true</property> 68 <!-- 69 加载映射文件 70 --> 71 <mapping resource="com/itheima09/hibernate/domain/Classes.hbm.xml" /> 72 <mapping resource="com/itheima09/hibernate/domain/Student.hbm.xml" /> 73 </session-factory> 74 </hibernate-configuration>
1 <?xml version="1.0" encoding="utf-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <hibernate-mapping> 5 <class name="com.itheima09.hibernate.domain.Classes" lazy="true"> 6 <cache usage="read-only"/> 7 <id name="cid" length="5"> 8 <generator class="increment"></generator> 9 </id> 10 <property name="name" length="20"></property> 11 <property name="description" length="100"></property> 12 <!-- 13 fetch 抓取策略 14 join 通过做外链接 15 select 默认值 16 subselect 17 --> 18 <set name="students" cascade="all" fetch="select" lazy="true"> 19 <cache usage="read-only"/> 20 <!-- 21 key代表外键 22 用来关联classes表和student表,用于在hibernate低层生成sql语句 23 --> 24 <key> 25 <column name="cid"></column> 26 </key> 27 <!-- 28 建立类与类之间的关联,用于客户端的编码 29 --> 30 <one-to-many class="com.itheima09.hibernate.domain.Student"/> 31 </set> 32 </class> 33 </hibernate-mapping>
1 <?xml version="1.0" encoding="utf-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <hibernate-mapping> 5 <class name="com.itheima09.hibernate.domain.Student"> 6 <id name="sid" length="5"> 7 <generator class="increment"></generator> 8 </id> 9 <property name="name" length="20"></property> 10 <property name="description" length="100"></property> 11 <!-- 12 column 为外键 13 --> 14 <many-to-one name="classes" column="cid" 15 class="com.itheima09.hibernate.domain.Classes" cascade="save-update" lazy="false"> 16 </many-to-one> 17 </class> 18 </hibernate-mapping>
1 import java.util.Iterator; 2 import java.util.List; 3 import java.util.Set; 4 5 import org.hibernate.Session; 6 import org.hibernate.Transaction; 7 import org.junit.Test; 8 import org.omg.CORBA.TRANSACTION_MODE; 9 10 import com.itheima09.hibernate.domain.Classes; 11 import com.itheima09.hibernate.domain.Student; 12 import com.itheima09.hibernate.utils.HibernateUtils; 13 14 public class SessionFactoryCacheTest extends HibernateUtils{ 15 @Test 16 public void testGet(){ 17 Session session = sessionFactory.openSession(); 18 Classes classes = (Classes)session.get(Classes.class, 1L); 19 System.out.println(sessionFactory.getStatistics().getEntityLoadCount());//输出的值为1 20 session.close();//一级缓存已经关闭了 21 session = sessionFactory.openSession();//该session是一个新的session 22 classes = (Classes)session.get(Classes.class, 1L);//没有发出sql语句 23 session.close(); 24 } 25 26 @Test 27 public void testSaveClasses(){ 28 Session session = sessionFactory.getCurrentSession(); 29 Transaction transaction = session.beginTransaction(); 30 Classes classes = new Classes(); 31 classes.setName("aaa"); 32 session.save(classes); 33 System.out.println(sessionFactory.getStatistics().getEntityLoadCount());//输出为0 34 transaction.commit(); 35 } 36 37 @Test 38 public void testUpdateClasses(){ 39 Session session = sessionFactory.getCurrentSession(); 40 Transaction transaction = session.beginTransaction(); 41 Classes classes = new Classes(); 42 classes.setCid(1L); 43 classes.setName("aa"); 44 session.update(classes); 45 System.out.println(sessionFactory.getStatistics().getEntityLoadCount());//输出为0 46 transaction.commit(); 47 } 48 49 @Test 50 public void testQuery() throws Exception{ 51 Session session = sessionFactory.openSession(); 52 //把classes表中的所有的数据放在了二级缓存中 53 List<Classes> classesList = session.createQuery("from Classes").list(); 54 System.out.println(sessionFactory.getStatistics().getEntityLoadCount()); 55 session.close(); 56 session = sessionFactory.openSession(); 57 List<Classes> list = session.createQuery("from Classes where cid in(1,2,3,4)").list(); 58 for(Classes classes1:list){ 59 Set<Student> students = classes1.getStudents(); 60 for(Student student:students){ 61 System.out.println(student.getName()); 62 } 63 } 64 session.close(); 65 Thread.sleep(1000l); 66 } 67 68 @Test 69 public void testOverToDisk() throws Exception{ 70 Session session = sessionFactory.openSession(); 71 //把classes表中的所有的数据放在了二级缓存中 72 List<Classes> classesList = session.createQuery("from Classes").list(); 73 session.close(); 74 Thread.sleep(1000l); 75 } 76 77 @Test 78 public void testSet(){ 79 Session session = sessionFactory.openSession(); 80 Classes classes = (Classes)session.get(Classes.class, 1L); 81 Set<Student> students = classes.getStudents(); 82 for(Student student:students){ 83 System.out.println(student.getName()); 84 } 85 //输出为1 86 System.out.println(sessionFactory.getStatistics().getCollectionLoadCount()); 87 session.close(); 88 } 89 }
查询缓存
概念
1、 查询缓存就是数据缓存
能够按照需求加载数据
2、 一级缓存和二级缓存都是对象缓存
在表中的一行有多少个字段,就会加载多少个数据
配置
1、 建立在二级缓存基础之上的
2、 开启查询缓存
案例1
说明:
当执行24行代码的时候,发出sql语句
当执行30行代码的时候,没有发出sql语句,因为利用了查询缓存
案例2
说明:
1、 当两次query.list的时候,都会发出sql语句
2、 原因是两次的查询hql语句不一样。
3、 从这里可以看出查询缓存的命中率比较低
案例3
从list的内存快照中可以看出,list里存放的不是持久化对象,而是name属性的值。
一级缓存和二级缓存存放的是持久化对象,如果集合中存放的不是持久化对象,则不能进入二级缓存中,但是能够进入查询缓存中。
数据缓存和对象缓存
1、 一级缓存和二级缓存是对象缓存,只能缓存持久化对象
2、 对象缓存的特别就是要把数据库表中所有的字段全部查询出来
3、 查询缓存是数据缓存,可以查询一个对象的部分属性,而且可以把部分属性放入到查询缓存中,查询缓存也支持对象。
1 <?xml version='1.0' encoding='utf-8'?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 5 <hibernate-configuration> 6 <!-- 7 一个session-factory代表一个数据库 8 --> 9 <session-factory> 10 <!-- 11 链接数据库的用户名 12 --> 13 <property name="connection.username">root</property> 14 <!-- 15 链接数据库的密码 16 --> 17 <property name="connection.password">root</property> 18 <!-- 19 链接数据库的驱动 20 --> 21 <property name="connection.driver_class"> 22 com.mysql.jdbc.Driver 23 </property> 24 <!-- 25 链接数据库的url 26 --> 27 <property name="connection.url"> 28 jdbc:mysql://localhost:3306/itheima09_hibernate 29 </property> 30 <!-- 31 方言 32 告诉hibernate用什么样的数据库 33 --> 34 <property name="dialect"> 35 org.hibernate.dialect.MySQLDialect 36 </property> 37 <!-- 38 validate 加载hibernate时,验证数据库的结构 39 update 加载hibernate时,检查数据库,如果表不存在,则创建,如果存在,则更新 40 create 每次加载hiberante,都会创建表 41 create-drop 每次加载hiberante,创建,卸载hiberante时,销毁 42 --> 43 <property name="hbm2ddl.auto">update</property> 44 <!-- 45 显示sql语句 46 --> 47 <property name="show_sql">true</property> 48 <!-- 49 格式化sql语句 50 --> 51 <property name="format_sql">true</property> 52 <!-- 53 session要从当前线程中产生 54 --> 55 <property name="current_session_context_class">thread</property> 56 <!-- 57 开启二级缓存 58 --> 59 <property name="cache.use_second_level_cache">true</property> 60 <!-- 61 二级缓存的供应商 62 --> 63 <property name="cache.provider_class"> 64 org.hibernate.cache.EhCacheProvider 65 </property> 66 <!-- 67 开启hibernate的统计机制 68 --> 69 <property name="hibernate.generate_statistics">true</property> 70 <!-- 71 开启查询缓存 72 --> 73 <property name="cache.use_query_cache">true</property> 74 <!-- 75 加载映射文件 76 --> 77 <mapping resource="com/itheima09/hibernate/domain/Classes.hbm.xml" /> 78 <mapping resource="com/itheima09/hibernate/domain/Student.hbm.xml" /> 79 </session-factory> 80 </hibernate-configuration>
1 <?xml version="1.0" encoding="utf-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <hibernate-mapping> 5 <class name="com.itheima09.hibernate.domain.Student"> 6 <id name="sid" length="5"> 7 <generator class="increment"></generator> 8 </id> 9 <property name="name" length="20"></property> 10 <property name="description" length="100"></property> 11 <!-- 12 column 为外键 13 --> 14 <many-to-one name="classes" column="cid" 15 class="com.itheima09.hibernate.domain.Classes" cascade="save-update" lazy="false"> 16 </many-to-one> 17 </class> 18 </hibernate-mapping>
1 <?xml version="1.0" encoding="utf-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <hibernate-mapping> 5 <class name="com.itheima09.hibernate.domain.Classes" lazy="true"> 6 <cache usage="read-only"/> 7 <id name="cid" length="5"> 8 <generator class="increment"></generator> 9 </id> 10 <property name="name" length="20"></property> 11 <property name="description" length="100"></property> 12 <!-- 13 fetch 抓取策略 14 join 通过做外链接 15 select 默认值 16 subselect 17 --> 18 <set name="students" cascade="all" fetch="select" lazy="true"> 19 <cache usage="read-only"/> 20 <!-- 21 key代表外键 22 用来关联classes表和student表,用于在hibernate低层生成sql语句 23 --> 24 <key> 25 <column name="cid"></column> 26 </key> 27 <!-- 28 建立类与类之间的关联,用于客户端的编码 29 --> 30 <one-to-many class="com.itheima09.hibernate.domain.Student"/> 31 </set> 32 </class> 33 </hibernate-mapping>
1 import java.util.Iterator; 2 import java.util.List; 3 import java.util.Set; 4 5 import org.hibernate.Query; 6 import org.hibernate.Session; 7 import org.hibernate.Transaction; 8 import org.junit.Test; 9 import org.omg.CORBA.TRANSACTION_MODE; 10 11 import com.itheima09.hibernate.domain.Classes; 12 import com.itheima09.hibernate.domain.Student; 13 import com.itheima09.hibernate.utils.HibernateUtils; 14 15 public class QueryCache extends HibernateUtils{ 16 @Test 17 public void testQueryCache(){ 18 Session session = sessionFactory.openSession(); 19 Query query = session.createQuery("from Classes"); 20 //允许把查询出来的集合放入到查询缓存中 21 query.setCacheable(true); 22 query.list(); 23 System.out.println(sessionFactory.getStatistics().getEntityLoadCount()); 24 session.close(); 25 session = sessionFactory.openSession(); 26 query = session.createQuery("from Classes where cid=1"); 27 //允许从查询缓存中提取数据 28 query.setCacheable(true); 29 query.list(); 30 session.close(); 31 } 32 33 @Test 34 public void testSessionFactory(){ 35 Session session = sessionFactory.openSession(); 36 Query query = session.createQuery("select name from Classes"); 37 //允许把查询出来的集合放入到查询缓存中 38 query.setCacheable(true); 39 query.list(); 40 System.out.println(sessionFactory.getStatistics().getEntityLoadCount()); 41 session.close(); 42 session = sessionFactory.openSession(); 43 query = session.createQuery("select name from Classes"); 44 //允许从查询缓存中提取数据 45 query.setCacheable(true); 46 query.list(); 47 session.close(); 48 } 49 }
Hql语句
单表
操作
案例1
案例2
说明:List中含有Object[],该数组中有两个元素,第一个元素为Long类型,第二个元素为String类型。
案例3
在持久化类中,必须有两个构造器
案例4
案例5
案例6
案例7
一对多
案例1
案例2
采用了左外链接,但是出来的结构不是很好。
案例3
说明:在join后面跟fetch,就为迫切左外链接。
案例4
案例5
说明:
如果用select,则不能用fetch,如果用fetch,则不能用select。
多对多
案例1
案例2
一对多和多对多
案例1
List<Classes>
Classes<Set<Student>>
Student<Set<Course>>
1 import java.util.Map.Entry; 2 import java.util.Set; 3 4 import org.hibernate.Query; 5 import org.hibernate.Session; 6 import org.hibernate.metadata.ClassMetadata; 7 import org.junit.Test; 8 9 import com.itheima09.hibernate.domain.Classes; 10 import com.itheima09.hibernate.domain.Student; 11 import com.itheima09.hibernate.manytomany.domain.Course; 12 import com.itheima09.hibernate.utils.HibernateUtils; 13 14 public class HqlTest extends HibernateUtils{ 15 16 @Test 17 public void testCreateTable(){ 18 19 } 20 21 @Test 22 public void testQueryClasses(){ 23 Session session = sessionFactory.openSession(); 24 List<Classes> classesList = session.createQuery("from Classes").list(); 25 session.close(); 26 } 27 28 @Test 29 public void testQueryClasses_Properties(){ 30 Session session = sessionFactory.openSession(); 31 List classesList = session.createQuery("select cid,name from Classes").list(); 32 session.close(); 33 } 34 35 @Test 36 public void testQueryClasses_Constructor(){ 37 Session session = sessionFactory.openSession(); 38 List classesList = session.createQuery("select new com.itheima09.hibernate.domain.Classes(cid,name) from Classes").list(); 39 session.close(); 40 } 41 42 /* 43 * 查询classes表中所有的数据的个数 44 */ 45 @Test 46 public void testQueryCount(){ 47 Session session = sessionFactory.openSession(); 48 Long count = (Long)session.createQuery("select count(*) from Classes").uniqueResult(); 49 System.out.println(count); 50 session.close(); 51 } 52 53 /** 54 * 带参数的查询 55 */ 56 @Test 57 public void testQuery_Parameter_1(){ 58 Session session = sessionFactory.openSession(); 59 Query query = session.createQuery("from Classes where name=?"); 60 query.setString(0, "aa"); 61 List<Classes> classesList = query.list(); 62 System.out.println(classesList.size()); 63 session.close(); 64 } 65 66 @Test 67 public void testQuery_Parameter_2(){ 68 Session session = sessionFactory.openSession(); 69 Query query = session.createQuery("from Classes where name=:name"); 70 query.setString("name", "aa"); 71 List<Classes> classesList = query.list(); 72 System.out.println(classesList.size()); 73 session.close(); 74 } 75 76 @Test 77 public void testQuery_Dynamic_Parameter(){ 78 /** 79 * key代表持久化类中属性的名称 80 * value代表属性的值 81 */ 82 Map<String, String> map = new HashMap<String, String>(); 83 map.put("name","aa"); 84 this.queryDynamic(map, Classes.class); 85 } 86 87 private void queryDynamic(Map<String, String> map,Class className){ 88 Session session = sessionFactory.openSession(); 89 StringBuffer buffer = new StringBuffer(); 90 /** 91 * classes持久化类的元数据 92 */ 93 ClassMetadata classMetadata = sessionFactory.getClassMetadata(className); 94 //得到持久化类的名称 95 buffer.append("from "+classMetadata.getEntityName()); 96 buffer.append(" where 1=1"); 97 //得到map中所有的key值 98 Set<String> keys = map.keySet(); 99 //拼接hql语句:查询条件 100 Iterator<String> iterator = keys.iterator(); 101 for(int i=0;i<keys.size();i++){ 102 String temp = iterator.next(); 103 buffer.append(" and "+temp+"=:"+temp); 104 } 105 Query query = session.createQuery(buffer.toString()); 106 /** 107 * 给所有的查询条件赋值 108 */ 109 for(Entry<String, String> entry:map.entrySet()){ 110 query.setString(entry.getKey(), entry.getValue()); 111 } 112 List<Classes> classesList = query.list(); 113 System.out.println(classesList.size()); 114 session.close(); 115 } 116 117 118 /** 119 * 一对多 120 */ 121 /** 122 * 等值链接 123 * 内链接 124 * 左外链接 125 * 迫切内链接 126 * 迫切左外链接 127 */ 128 @Test 129 public void testQueryClassesAndStudent_EQ(){ 130 Session session = sessionFactory.openSession(); 131 List list = session.createQuery("from Classes c,Student s where c.cid=s.classes.cid").list(); 132 session.close(); 133 } 134 135 @Test 136 public void testQueryClassesAndStudent_LeftJoin(){ 137 Session session = sessionFactory.openSession(); 138 List list = session.createQuery("from Classes c left join c.students s").list(); 139 session.close(); 140 } 141 142 /** 143 * 迫切左外链接 144 */ 145 @Test 146 public void testQueryClassesAndStudent_LeftJoin_fetch(){ 147 Session session = sessionFactory.openSession(); 148 List list = session.createQuery("from Classes c left outer join fetch c.students s").list(); 149 session.close(); 150 } 151 152 /** 153 * 迫切内连接 154 */ 155 @Test 156 public void testQueryClassesAndStudent_Innerjoin_fetch(){ 157 Session session = sessionFactory.openSession(); 158 List list = session.createQuery("from Classes c inner join fetch c.students s").list(); 159 session.close(); 160 } 161 162 /** 163 * 查询classes中的name和student中的name 164 */ 165 @Test 166 public void testQueryClassesPropertyAndStudentProperty(){ 167 Session session = sessionFactory.openSession(); 168 List list = session.createQuery("select new com.itheima09.hibernate.domain.ClassesView(c.name,s.name) " + 169 " from Classes c inner join c.students s").list(); 170 session.close(); 171 } 172 173 /** 174 * 多对多的迫切内连接 175 */ 176 @Test 177 public void testQueryCourseAndStudent_1(){ 178 Session session = sessionFactory.openSession(); 179 List<Course> list = session.createQuery("from Course c inner join fetch c.students s").list(); 180 session.close(); 181 } 182 @Test 183 public void testQueryCourseAndStudent_2(){ 184 Session session = sessionFactory.openSession(); 185 List<Student> list = session.createQuery("from Student s inner join fetch s.courses c").list(); 186 session.close(); 187 } 188 189 /** 190 * 多对多迫切左外链接 191 */ 192 @Test 193 public void testQueryCourseLeftouterjoin_fetch(){ 194 Session session = sessionFactory.openSession(); 195 List<Course> list = session.createQuery("from Course c left outer join fetch c.students s").list(); 196 session.close(); 197 } 198 199 /** 200 * 一对多和多对多的结合 201 * 202 * 如果用迫切内链接做,最好查找核心表 203 */ 204 /** 205 * 内连接 206 */ 207 @Test 208 public void testQueryManyToManyToOne_1(){ 209 Session session = sessionFactory.openSession(); 210 StringBuffer buffer = new StringBuffer(); 211 buffer.append("from Student s inner join fetch s.courses c inner join fetch s.classes cc"); 212 List list = session.createQuery(buffer.toString()).list(); 213 session.close(); 214 } 215 216 @Test 217 public void testQueryManyToManyToOne_2(){ 218 Session session = sessionFactory.openSession(); 219 StringBuffer buffer = new StringBuffer(); 220 //from Course c inner join fetch c.students s inner join fetch s.classes cc 221 buffer.append("from Classes c inner join fetch c.students s inner join fetch s.courses cc"); 222 List list = session.createQuery(buffer.toString()).list(); 223 session.close(); 224 } 225 226 @Test 227 public void testList(){ 228 Session session = sessionFactory.openSession(); 229 List list = session.createQuery("select new list(cid,name) from Classes").list(); 230 session.close(); 231 } 232 233 @Test 234 public void Map(){ 235 Session session = sessionFactory.openSession(); 236 /** 237 * n:ads 238 c:1 239 n:adsf 240 c:2 241 */ 242 //别名为map中的key值,value值为属性的值 243 List<Map<String, Object>> list = session.createQuery("select new map(cid as c,name as n) from Classes").list(); 244 for(Map<String, Object> map:list){ 245 for(Entry<String, Object> entry:map.entrySet()){ 246 System.out.println(entry.getKey()+":"+entry.getValue()); 247 } 248 } 249 session.close(); 250 } 251 252 /** 253 * 分页 254 */ 255 @Test 256 public void testDispage(){ 257 Session session = sessionFactory.openSession(); 258 Query query = session.createQuery("from Classes"); 259 query.setFirstResult(1);//当前页的第一行在集合中的位置 260 query.setMaxResults(2);//当前页有多少行 261 List<com.itheima09.hibernate.onetomanytomany.Classes> classesList = query.list(); 262 for(com.itheima09.hibernate.onetomanytomany.Classes classes:classesList){ 263 System.out.println(classes.getCid()); 264 } 265 session.close(); 266 } 267 }
Hibernate内部的list
Hibernate内部的map
分页
原生态的sql查询
接口回调
https://blog.csdn.net/liangxw1/article/details/50701205
1 public List findByPage(final String hql, 2 final int offset, final int pageSize) 3 { 4 //通过一个HibernateCallback对象来执行查询 5 List list = getHibernateTemplate() 6 .executeFind(new HibernateCallback() 7 { 8 //实现HibernateCallback接口必须实现的方法 9 public Object doInHibernate(Session session) 10 throws HibernateException, SQLException 11 { 12 //执行Hibernate分页查询 13 List result = session.createQuery(hql) 14 .setFirstResult(offset) 15 .setMaxResults(pageSize) 16 .list(); 17 return result; 18 } 19 }); 20 return list; 21 }
第5行:获取Hibernatetemplate对象
第6行:执行Hibernatetemplate的 executeFind ()方法,并且传入HibernateCallback接口的实例化对象(匿名内部类)
这里的Hibernatetemplate对象 就类似 参考文章 的B的对象;而Hibernatetemplate对象中有一个方法是接收HibernateCallback接口的实例化对象,所以直接调用HibernateCallback接口的实例化对象的方法
interface AA{ public String method1(); public int method2(); } public class InterFaceCallBack { public static void main(String[] args){ BB bb=new BB(); bb.Method(new AA() { @Override public String method1() { return "I am AAImpl Method1"; } @Override public int method2() { return 1+1; } }); } } class BB{ public int Method(AA aa){ String a1=aa.method1(); System.out.println("a1="+a1); int a2=aa.method2(); System.out.println("a2="+a2); return 0; } }