今天小节了一下:
1 Hibernate 中查询.
2 inverse 和 cascade的对比.
3 二级缓存和查询缓存的使用。
hibernate.cfg.xml 如下:
<!-- 指定使用 Echache做缓存提供者 --> <property name="hibernate.cache.provider_class"> org.hibernate.cache.EhCacheProvider </property> <!-- 使用查询缓存(查询缓存在二级缓存的基础上使用) --> <property name="hibernate.cache.use_query_cache">true</property>
ehcache.xml(用于二级缓存)如下:
<ehcache> <!-- 内存中存不下时存放在硬盘的位置 --> <diskStore path="F:\\temp" /> <defaultCache maxElementsInMemory="2000" eternal="false" timeToIdleSeconds="1000" timeToLiveSeconds="1000" overflowToDisk="true"> </defaultCache> <cache name="com.isw2.bo.TelBO" maxElementsInMemory="500" eternal="false" timeToIdleSeconds="1000" timeToLiveSeconds="1000" overflowToDisk="true" /> <cache name="com.isw2.bo.UserBO" maxElementsInMemory="500" eternal="false" timeToIdleSeconds="1000" timeToLiveSeconds="1000" overflowToDisk="true" /> <cache name="com.isw2.bo.UserBO.telBOs" maxElementsInMemory="500" eternal="false" timeToIdleSeconds="1000" timeToLiveSeconds="1000" overflowToDisk="true" /> <cache name="org.hibernate.cache.StandardQueryCache" maxElementsInMemory="100" eternal="true" overflowToDisk="true"> </cache> <cache name="org.hibernate.cache.UpdateTimestampsCache" maxElementsInMemory="100" eternal="true" overflowToDisk="true"> </cache> </ehcache>
TelBO.hbm.xml 如下:
<class name="com.isw2.bo.TelBO" table="t_tel" catalog="many_to_one" lazy="true"> <!-- 读写策略 --> <cache usage="read-write" /> <id name="telId" column="telId"> <generator class="native"></generator> </id> <property name="telNumber" column="telNumber" length="32" type="string"> </property> <many-to-one name="userBO" fetch="select" column="userId" lazy="proxy"> </many-to-one> </class>
UserBO.hbm.xml如下:
<class name="com.isw2.bo.UserBO" table="t_user" catalog="many_to_one" lazy="true"> <!-- 使用二级缓存 --> <cache usage="read-write" /> <id name="userId" column="userId"> <generator class="native"></generator> </id> <property name="userName" column="userName" length="32" type="string"> </property> <set name="telBOs" fetch="select" cascade="all" lazy="true" inverse="true"> <!-- 使用二级缓存 --> <cache usage="read-write" /> <key column="userId"></key> <one-to-many class="com.isw2.bo.TelBO" /> </set> </class>
/**
* 关于 inverse="true"
*/
public void update() {
Session session = HibernateSessionFactory.getSession();
Transaction tr = session.beginTransaction();
Query query = session.createQuery("from UserBO ub where ub.userId = 7");
UserBO userBO = (UserBO) query.uniqueResult();
TelBO telBO = new TelBO("9058492", userBO);
userBO.getTelBOs().add(telBO);
session.update(userBO);
tr.commit();
session.close();
/**
* 在one-to-many 中 设置 inverse="true" 表示由many方维护数据间的关系. 注意: 区别于 cascade
* 表示需要哪些维护数据间的关系(all:所有情况下均进行关联操作;
* none:所有情况下均不进行关联操作,这是默认值;save-update:在执行save/update/saveOrUpdate时进行关联操作;
* delete:在执行delete时进行关联操作。 )
*
* 对下面的操作分析可知,当由one方维护时数据先存入数据库,然后根据 one 执行更新操作;
* 由many 方维护时,数据先查询,然后根据查询结果存入数据库
*/
/**
* inverse="true" 时操作如下:
* Hibernate: select userbo0_.userId as userId1_,
* userbo0_.userName as userName1_ from many_to_one.t_user userbo0_
* where userbo0_.userId=7
*
* Hibernate: select telbos0_.userId as
* userId1_, telbos0_.telId as telId1_, telbos0_.telId as telId0_0_,
* telbos0_.telNumber as telNumber0_0_, telbos0_.userId as userId0_0_
* from many_to_one.t_tel telbos0_ where telbos0_.userId=?
*
* Hibernate:
* insert into many_to_one.t_tel (telNumber, userId) values (?, ?)
*
*
*
* inverse="false" 时操作如下:
*
* Hibernate: select userbo0_.userId as userId1_,
* userbo0_.userName as userName1_ from many_to_one.t_user userbo0_
* where userbo0_.userId=7
*
* Hibernate: select telbos0_.userId as
* userId1_, telbos0_.telId as telId1_, telbos0_.telId as telId0_0_,
* telbos0_.telNumber as telNumber0_0_, telbos0_.userId as userId0_0_
* from many_to_one.t_tel telbos0_ where telbos0_.userId=?
*
* Hibernate:insert into many_to_one.t_tel (telNumber, userId) values (?, ?)
* Hibernate: update many_to_one.t_tel set userId=? where telId=?
*/
}
/**
* 根据Bean 查询对象
*/
public void findByEntity() {
Session session = HibernateSessionFactory.getSession();
UserBO userBO = (UserBO) session.load(UserBO.class, new Long(7));
/**
* Query query = session.createQuery("from TelBO tb where tb.userBO =
* ?"); query.setParameter(0, userBO); TelBO telBO = new TelBO();
* telBO.setTelNumber("591201270");
*/
// 这里把UserBO 当作Bean 来使用,userBO.getUserId 在这里可以提供参数注意:userId
Query query = session.createQuery("from TelBO tb "
+ "where tb.telId =:userId");
query.setProperties(userBO);
System.out.println(query.setMaxResults(1).uniqueResult());
session.close();
}
/**
* 根据 Alias 联合查询(distinct 无法解决)
*/
public void findByJoinAlias() {
Session session = HibernateSessionFactory.getSession();
Criteria cr = session.createCriteria(UserBO.class);
cr.createAlias("telBOs", "tb");// 别名的使用
cr.add(Restrictions.like("tb.telNumber", "%"));
// //这样查询结果仅有userName 一个字段
// cr.setProjection(Projections.distinct(Projections.property("userName")));
// //这只是在结果集中做了处理分页时无法使用
// cr.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
List list = cr.list();
for (Object object : list) {
System.out.println(object);
}
session.close();
}
/**
* 通过HQL 联合查询
*/
public void findByJoinHQL() {
Session session = HibernateSessionFactory.getSession();
// fetch 查询和 非fetch 查询, SQL语句相同,不同的是前者以 对象形式 返回,后者以数组形式返回
// Query query = session.createQuery("from UserBO ub inner join
// ub.telBOs");
// Query query = session
// .createQuery("from UserBO ub inner join fetch ub.telBOs");
Query query = session
.createQuery("select distinct ub from UserBO ub inner join fetch ub.telBOs");
List list = query.list();
for (Object object : list) {
System.out.println(object);
}
session.close();
}
/**
* 使用二级缓存(批量更新数据时为提高效率通过session.setCacheMode设置缓存模式)
*/
public void testCache() {
System.out.println("开始查询.....");
Session session = HibernateSessionFactory.getSession();
Query query = session.createQuery("from UserBO");
List list = query.list();
for (Object object : list) {
System.out.println(object);
}
session.close();
System.out.println("使用二级缓存......");
/**
* 查询SQL: Hibernate: select userbo0_.userId as col_0_0_ from
* many_to_one.t_user userbo0_
*
* 这里先查询Id 然后在缓存中根据id查找. 这里要注意,使用的是query.iterate.
* 因为它会先查询Id,再根据Id查询对象,如二级缓存中有则直接取,否则就去数据库查询.
* 之前一次查询后数据已放入二级缓存,第二次就没有查询数据库.
*
* 集合的缓存中存放的是Id,然后根据Id 查询二级缓存
*
* 如果用query.list 则要使用查询缓存.
*/
session = HibernateSessionFactory.getSession();
query = session.createQuery("from UserBO");
Iterator<Object> iterator = query.iterate();
for (; iterator.hasNext();) {
Object object = iterator.next();
System.out.println(object);
}
session.close();
}
/**
* 使用查询缓存
*/
public void testSearchCache() {
System.out.println("开始查询.....");
Session session = HibernateSessionFactory.getSession();
Query query = session.createQuery("from UserBO");
// 设置使用查询缓存(查询缓存默认不使用,这里要显示启动)
query.setCacheable(true);
// 设置缓存区域
query.setCacheRegion("com.isw2.bo.UserBO");
// ------------------------------------
List list = query.list();
for (Object object : list) {
System.out.println(object);
}
session.close();
System.out.println("使用查询缓存......");
session = HibernateSessionFactory.getSession();
query = session.createQuery("from UserBO");
// 设置使用查询缓存(两次使用同样的缓存区域)
query.setCacheable(true);
query.setCacheRegion("com.isw2.bo.UserBO");
// ------------------------------------
list = query.list();
for (Object object : list) {
System.out.println(object);
}
/**
* 在这里查询缓存类似于集合缓存。通过查询语句和 Id 集的方式存放查询结果,然后在二级缓存中查询结果
*/
}
这里以又向关联为主。二级缓存因为命中率不高使用的不多,自己也不是很熟。
参考:
http://www.iteye.com/topic/18904
http://rujingzhang.iteye.com/blog/219487
http://www.blogjava.net/i369/articles/219408.html