首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

(四)Hibernate中的many-to-one和one-to-many关系

2012-10-27 
(4)Hibernate中的many-to-one和one-to-many关系今天小节了一下:1 Hibernate 中查询.2 inverse 和 cascade

(4)Hibernate中的many-to-one和one-to-many关系

今天小节了一下:

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 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 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 /></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 在这里可以提供参数注意:userIdQuery 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

热点排行