一、应用<class> 标签的<dynamc-insert> 和<dynamic-update> 属性
问题:没有使用<dynamc-insert> 和<dynamic-update> 属性,update或者insert 发起的hql 默认会更新所有的字段。
比如:Book book = hibernateDao.load(id);
book.setName("chen");
后台HQL update book set name=?,price=?,date=? where id =?;
设置<dynamc-insert> 和<dynamic-update> 属性为true 会根据实际需要设置新增或者更新的字段,
后台HQL update book set name=? where id=?;
二、延迟加载
(1)、实体对象的延迟加载
配置文件设置
<hibernate-mapping>
<class name="com.cn...Tuser"
table="TUSER"
lazy=true>
</hibernate-mapping>
Tuser user=session.load(Tuser.class,new Integer(2)) ----(1)
user.getName() ------(2)
配置文件 lazy=true 设置为延迟加载,只有当客户当程序真真调用实体类的取值方法(执行(2)), Hibernate 才会执行数据库查询操作。在执行(1)过程中其实首先是构造了一个代理类,把目标类放在代理类的target属性中,且其所有的属性都是null,日志没有打印,说明还没执行SQL语句。
而如果是lazy=false 则程序执行到(1)的时候就有日志打印,说明:Hibernate已经从库表中取出记录,构造了一个完整的Tuser对象。
(2)、集合的延迟加载
配置文件
<hibernate-mapping>
<class name="com.cn...Tuser"
table="TUSER"
>
<set name="address"
table="TUSER"
layz=true
casecade="all" //所有的操作都进行关联操作 save update delete
inverse="false">//维护两个实体的关系,false自己维护,true对方维护
<key column="TUSER_ID"></key>
<one-to-many class="cn.com...ADDRESS"></one-to-many>
<set>
</hibernate-mapping>
eg:
Tuser user=(Tuser)session.load(Tuser.class,new Integer(2))
set addSet=user.getAddress() -------(1)
Iterator iterator=addSet.ietrator(); --------(2)
while(iterator.hasNext()){}
程序执行到(1) 时,address数据尚未读入,只是一个net.sf.hibernate.collection.Set实例
只有在执行到(2)时数据才真真载入,这就是延迟加载的集合延迟加载机制。
(3)属性的延迟加载
<hibernate-mapping>
<class name="com.cn...Tuser"
table="TUSER"
>
<property
name="resume"
type="java.lang.Integer"
column="RESUME"
lazy="true"
/>
</hibernate-mapping>
while(iterator.hasNext()){
user.getName();
user.getResume();
}
日志会执行两条SQL语句,第一条加载非延迟加载字段,第二条加载了延迟加载字段
三、抓取策略
1、默认的fetch策略是 select
<manyh-to-one name="classes" column="classesid" fetch="select"/> 同理 集合上也是<set name="students" cascade="all" fetch="select"><key column="classid"/><one-to-many class="cn.com.student"/></set>
例外发送一条sql语句抓取当前对象关联实体或集合,总共发生两天sql语句
2、 fetch="join",总共发生一条sql语句,通过left out 左外连接直接加载关联对象或集合,在这种情况下lazy 会失效。
3、 集合fetch="subselect" 主要是对hql起作用
List list = session.createQuery("select c from classes c where c.id in(1,2,3) ").list();
for (Iterator iterator = list.iterator(),iterator.hasNext()) {
Classes classes = (Classes)iterator.next();
System.out.println("classes.name="+classes.getName());
for (Iterator iterator1 = classes.getStudents().iterator();iterator1.hasNext()){
Student student = (Student)iterator1.next();
System.out.println("student.name="+student.getName());
}
}
对于hql one-to-many 上设置 fetch="select" 则每次查出一个班级都会再发一条sql语句查出对应的班级
日志:Hibernate:select classes0_.id from t_class classes0_ where classes0_.id in(1,2,3);
classes.name="班级0";
Hibernate:select student0_.id,student0_.name from t_student student0_ where student0_.classesid=? //查出第一个班级的
而如果设置fetch = "subSelect" 则会通过子查询把班级对应的学生一块查出.
Hibernate:select student0_.id,student0_.name from t_student student0_ where student0_.classesid in(select classes0_.id from t_class classes0_ where classes0_.id in(1,2,3));
4、批量加载实体 batch-size 有组与优化性能
List list = session.createQuery("select s from Student where s.id in(:ids)").list()
.setParameterList("ids",new Object[]{1,3,4,5,11,6,7,8,9,10});
.list();
for (Iterator iterator = list.iterator();iterator.hasNext()){
Student student = (Student)iterator.next();
System.out.println("student.name="+student.getName());
System.out.println("student.classes.name="+student.getClasses.getName());
}
每循环一次,都会发一条sql 语句,把这个学生对于的班级查询出来,所以会发10条这样的sql
日志:select classes0_.id,classes0_.name from t_classes classes0_ where classes0_.id=?
在Classes.hbm.xml文件里 <Class name="ClassesImpl" table="t_classes" batch-size=5>
日志:select classes0_.id,classes0_.name from t_classes classes0_ where classes0_.id in(?,?,?,?,?);
5、批量加载集合
同理在<set name="students" batch-size="5" cascade ="all">
<key column="classesid">
<one-to-many classes="cn.com.Student"/>
</set>