在Domain Moudel中,经常会碰到一个域对象中包含另外一个域对象的列表,例如:一个blog的文章会有多个回复。我们就拿blog来做实例说明,情形一:获取blog的文章信息展示给用户,此内容只包括Article对象的信息;情形二:获取单个文章Article的信息,包括用户对这个文章的回复信息。
//文章对象 Article
public class Article{
public String articleId;
public String title;
public String content;
public String userId;
public Date createTime;
public List reviewList;//Review域对象list
……//其他属性,get,set方法;
}
//回复对象 Review
public class Review{
public String reviewId;
public String title;
public String content;
public String articleId;
public String userId;
……//其他属性,get,set方法;
}
ibatis的一对多的配置文件如下:
……
如果我们要实现延迟加载(lazy loadding)的功能,仅仅配置上述xml文件还是不够的,在ibatis的主配置文件sql-map-config.xml中,需要把ibatis的两项配置做一下修改。
lazyLoadingEnabled设置系统是否实现延迟加载机制,enhancementEnabled设置是否用字节码强制机制,通过字节码强制机制可以为lazy loadding带来性能方面的改进;当用户 getSqlMapClientTemplate().queryForList("findArticle",article)的时候,实际上只是执行了查询article表的信息,而在Article对象中getReview()的时候,才会执行后面的查询Review对象的语句;这样在首页访问Article列表的时候就不用加载Review的信息,而在点击单个文章(Article)浏览的时候需要回复对象Review的时候,则会执行getReviewByArticleId的查询操作,把列表信息给出来。这样做明显的减少了代码的负责程度,按需提取信息也提升了系统的性能!
如果是settings中配置useStatementNamespaces = "true"(是否使用Statement命名空间)的话,上面的xml配置resultMap中的延迟加载信息应该写成:select = "Article.getReviewByArticleId",同时dao中也要写成:getSqlMapClientTemplate().queryForList("Article.findArticle",article);
下面是做一下简单的测试代码:
public void testListLazyLoading() {
ArticleDao articleDao = (ArticleDao) this.getApplicationContext().getBean("articleDao");
Article article = new Article();
article.setArticleId("00000005");
List list = articleDao.listLazyLoading(article);
for (int i = 0; i < list.size(); i++) {
Article articleTmp = (Article) list.get(i);
//List reviewList = articleTmp.getReviewList();
System.out.println(i + "---------ArticleId=" + articleTmp.getArticleId());
//for(Review review:reviewList){
//System.out.println( "---------reviewId=" + review.getReviewId());
//}
}
}
执行上面测试语句的时候,仅仅查询acticle表,只有去掉注释的时候,才会把review表中的信息查询出来。
参考资料:
1:夏昕 xiaxin(at)gmail.com ibatis开发指南
2:Clinton Begin iBATIS SQL Maps2
3:Owen Cline DB2 UDB、WebSphere 和 iBATIS
卓望java工程师郭经干对完成本文亦有贡献!原创文章,转载请注明原文地址!