85-002-16 利用hibernate的级联功能实现(N+1)

来源:互联网 发布:js 跳转url 编辑:程序博客网 时间:2024/06/05 09:36

图文版:http://note.youdao.com/yws/public/redirect/share?id=abc20790e48da5130e227d9390e4df92&type=false
资源文件下载 https://yunpan.cn/OcRaTMHR3NWIIf  访问密码 4b2c



16.1 首先在类category中增加一个相关类account
    Category.java
private Account account ; //每一个类别对应一个管理员,一个管理员对应多个类别,属于多对一的关系
//省略getter、setter

    定义其相关的hibernate配置文件

    Category.hbm.xml

        <!-- lazy="false":表示级联查询时候会关联其他对象 -->
        <!-- class="Account":父节点已经配置了package="cn.it.shop.modal"所以无需类全名 -->
        <many-to-one name="account" class="Account" lazy="false" fetch="join">
         <column name="aid"/>
        </many-to-one>
16.2 定义类别查询并要关联到管理员
    cn.it.shop.service.CategoryService.java
public List<Category> queryJionAccount(String type) ;

    定义其实现的子类

    cn.it.shop.service.impl.CategoryServiceImpl.java

@Override
 public List<Category> queryJionAccount(String type) {
  return this.getSession()
    .createQuery("FROM Category c WHERE c.type LIKE :type")
    .setString("type", "%"+type+"%")
    .list();
 }

    然后马上定义测试用例

    cn.it.CategoryServiceImplTest.java

@Test //测试级联操作
 public void testQueryJionAccount(){
  for(Category c:categoryService.queryJionAccount("")){
   System.out.println(c);
  }
 }
    此处牵扯到一个N+1的问题:1表示查找当前的对象,N表示查找关联的对象,效率比较低,在hibernate的配置文件中 lazy:表示是否加载关联对象,true表示延迟加载,false表示及时;fetch:则表示以什么样的方式来加载关联对象 select或者join 默认是select即N+1的方式(join在many-to-one中无效)
16.3 由于N+1的问题上的各种千奇百怪的需求,而寄希望仅仅通过XML配置来解决会往往力不从心,所以最简单粗暴的解决方式就是直接自己写HQL或SQL语句。在这方面mybatis就做的很好。
    首先在配置中干掉lazy="false" fetch="join" ,下面是解决的方案
      Category.hbm.xml
<many-to-one name="account" class="Account">
         <column name="aid"/>
        </many-to-one>

    cn.it.shop.service.impl.CategoryServiceImpl.java

public List<Category> queryJionAccount(String type) {
  return this.getSession()
    .createQuery("FROM Category c LEFT JOIN c.account WHERE c.type LIKE :type")
    .setString("type", "%"+type+"%")
    .list();
 }

16.4 然后经过测试发现出现了测试异常    

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to cn.it.shop.modal.Category
...
    只需要修改以下文件
     cn.it.shop.service.impl.CategoryServiceImpl.java
public List<Category> queryJionAccount(String type) {
  return this.getSession()
    .createQuery("FROM Category c LEFT JOIN FETCH c.account WHERE c.type LIKE :type")
    .setString("type", "%"+type+"%")
    .list();
 }

16.5 现在让上面模糊查询的结果实现分页显示

    cn.it.shop.service.CategoryService.java

//page表示显示第几页,size表示每页显示的数量
 public List<Category> queryJionAccount(String type,int page,int size) ;

    cn.it.shop.service.impl.CategoryServiceImpl.java

@Override
 public List<Category> queryJionAccount(String type,int page,int size) {
  return this.getSession()
    .createQuery("FROM Category c LEFT JOIN FETCH c.account WHERE c.type LIKE :type")
    .setString("type", "%"+type+"%")
    .setFirstResult(page)
    .setMaxResults(size)
    .list();
 }

0 0
原创粉丝点击