Hibernate的检索、级联操作以及批处理
HIbernate的检索方式
立即检索:查询返回的对象中包含所有的属性(将所有的属性都加载)
延迟检索(延迟加载):查询返回的对象仅仅包含OID(Object Identifier:对象标识符),其他属性为空,只有在调用该对象的setter或者getter方法时,Hibernate才会根据OID从数据库中查询并加载其他属性。
实际上Hibernate从3.x版本之后,默认全部采用延迟加载的方式
延迟加载的级别
类级别:
<class lazy="true/false"/>
字段级别:
<property lazy="true/false"/>
关联级别:
<one-to-one lazy="true/false"/> <set lazy="true/false"/>
**注意:**lazy=”false”则采用立即检索
测试
我们知道 Session的load方法采用的是延迟加载方式,那么当我们使用load方法后不去使用返回的持久化对象,这个时候有做查询吗?
//启动事务1
trans=session.beginTransaction();
Student student=session.load(Student.class, "2015");
trans.commit();
运行结果是,Hibernate并未输出任何SQL语句,也就是说并未做查询,只是保存了对象的OID,如果我们改变一下:
//启动事务1
trans=session.beginTransaction();
Student student=session.load(Student.class, "2015");
//System.out.println(student);
trans.commit();
检索并输出,这个时候Hibernate才输出了SQL语句:Hibernate: select……
映射配置文件示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.li.association.one2many.pojo">
<class name="Order" table="T_ORDER" lazy="true">
<cache usage="read-only"/>
<id name="id" type="long" column="ID"></id>
<property name="orderedDate" type="date" column="ORDERED_DATE"></property>
<property name="shippedDate" type="date" column="SHIPPED_DATE"></property>
<property name="total" type="double" column="TOTAL"></property>
<bag name="orderLines" cascade="all" inverse="true" lazy="true">
<cache usage="read-only"/>
<key column="ORDER_ID"/>
<one-to-many class="OrderLine"/>
</bag>
</class>
</hibernate-mapping>
外连接检索
在映射文件中通过设置属性 outer-join 来控制,针对多表查询。Hibernate的外连接就是 SQL 语句中的 left outer join。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.li.association.one2many.pojo">
<class name="Order" table="T_ORDER" lazy="true">
<cache usage="read-only"/>
<id name="id" type="long" column="ID"></id>
<property name="orderedDate" type="date" column="ORDERED_DATE"></property>
<property name="shippedDate" type="date" column="SHIPPED_DATE"></property>
<property name="total" type="double" column="TOTAL"></property>
<bag name="orderLines" cascade="all" inverse="true" outer-join="true">
<cache usage="read-only"/>
<key column="ORDER_ID"/>
<one-to-many class="OrderLine"/>
</bag>
</class>
</hibernate-mapping>
级联操作
在对象-关联的映射文件中,用于映射持久化类之间关联关系的元素,如 <set>、<many-to-one>、<one-to-one>元素,都有一个cascade属性,它用于指定如何操作与当前对象关联的其他对象。
cascade属性值:
none:在保存、更新或删除当前对象时,忽略其他关联的对象,但是会级联查询操作。它是默认值
save-update:当通过Session的save、update、以及saveOrUpdate方法来保存或更新当前对象时,级联保存所有关联的新建的临时对象,并且级联更新所有的关联的游离对象或持久化对象。
delete:当通过Session的delete方法删除当前对象时,级联删除所有关联的对象。
all:包含save-update和delete的行为。此外,对当前对象执行evict(清理该缓存)或lock方法操作时,也会对所有的关联的持久化对象执行evict或lock方法操作。
delete-orphan:删除所有和当前对象解除关联关系的对象。
all-deleteorphan:包含all和delete-orphan的行为
<set>元素的inverse属性
默认为inverse=”false”,表示子表的外键由父表来维护,会出现多条update语句,用父表的主键来更新子表的外键,这样子表的外键不会出现null的情况。
当inverse=”true”时,子表的外键由子表来维护,不会出现update语句,这样外键可能会出现null。
一对多中inverse可以不加,在多对多的情况下,inverse一定要设置为true,在任何一方都可以。
Hibernate中的批处理
Hibernate的配置文件
设置批处理的数量大小
<session-factory>
<property name="hibernate.jdbc.batch_size">50</property>
</session-factory>
Hibernate批处理代码
因为我们设置了批处理容量上限为50,所以到达上限时,就需要清理一下缓存。
Transaction trans=session.beginTransaction();
for(int i=0; i<1000; i++){
session.save(......);
if(i%50==0){
session.flush();
session.clear();
}
}
trans.commit();
**注意:**Hibernate的批处理操作性能并不是很好,相对于JDBC的批处理来说,速度上要慢一些。