欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SSH框架网上商城项目第5战之商品类别级联查询和分页功能

程序员文章站 2024-03-11 20:40:07
上文我们完成了easyui菜单的实现,点击查看,这一节我们主要来写一下categoryserviceimpl实现类,完成数据库的级联查询。一般项目从后往前做,先做servi...

上文我们完成了easyui菜单的实现,点击查看,这一节我们主要来写一下categoryserviceimpl实现类,完成数据库的级联查询。一般项目从后往前做,先做service(我们没有抽取dao,最后再抽取),做完了再做上面层。
在写之前,先看一下数据库中的表的情况:

drop database if exists shop; 
/*创建数据库,并设置编码*/ 
create database shop default character set utf8; 
 
use shop; 
/*删除管理员表*/ 
drop table if exists account; 
/*删除商品类别表*/ 
drop table if exists category; 
 
/*============================*/ 
/*   table:管理员表结构            */ 
/*============================*/ 
create table account 
( 
  /* 管理员编号,自动增长 */ 
  id int primary key not null auto_increment, 
  /* 管理员登录名 */ 
  login varchar(20), 
  /* 管理员姓名 */ 
  name varchar(20), 
  /* 管理员密码 */ 
  pass varchar(20) 
); 
 
/*============================*/ 
/*   table:商品类别表结构           */ 
/*============================*/ 
create table category 
( 
  /* 类别编号,自动增长 */ 
  id int primary key not null auto_increment, 
  /* 类别名称 */ 
  type varchar(20), 
  /* 类别是否为热点类别,热点类别才有可能显示在首页*/ 
  hot bool default false, 
  /* 外键,此类别由哪位管理员管理 */ 
  account_id int, 
  constraint aid_fk foreign key(account_id) references account(id) 
); 

主要有两张表,商品类别表和管理员表,并且商品类别表中提供了一个外键关联管理员表。也就是商品和管理员是多对一的关系。现在我们开始编写查询商品的类别信息,需要级联管理员。
1. 实现级联查询方法
首先在categoryservice接口中定义该方法:

public interface categoryservice extends baseservice<category> { 
  //查询类别信息,级联管理员 
  public list<category> queryjoinaccount(string type); //使用类别的名称查询 
} 

然后我们在categoryservice的实现类categoryserviceimpl中实现这个方法:

@service("categoryservice") 
public class categoryserviceimpl extends baseserviceimpl<category> implements categoryservice { 
 
  @override 
  public list<category> queryjoinaccount(string type) { 
    string hql = "from category c where c.type like :type"; 
    return getsession().createquery(hql) 
        .setstring("type", "%" + type + "%").list(); 
  } 
} 

在两个model中我们配一下关联注解:

//category类中 
@manytoone(fetch = fetchtype.eager) 
@joincolumn(name = "account_id") 
public account getaccount() { 
  return this.account; 
} 
//account类中 
@onetomany(cascade = cascadetype.all, fetch = fetchtype.lazy, mappedby = "account") 
public set<category> getcategories() { 
  return this.categories; 
} 

然后我们在测试类中测试一下:

@runwith(springjunit4classrunner.class) 
@contextconfiguration(locations="classpath:beans.xml") 
public class categoryserviceimpltest { 
 
  @resource 
  private categoryservice categoryservice; 
   
  @test 
   public void testqueryjoinaccount() { 
    for(category c : categoryservice.queryjoinaccount("")) { 
       system.out.println(c); 
       system.out.println(c.getaccount()); 
    } 
  } 
} 

2. 级联查询存在的问题
我们看一下控制台的输出可以看出,它发了不止一条sql语句,但是我们明明只查询了一次,为什么会发这么多语句呢?这就是常见的1+n问题。所谓的1+n问题,就是首先发出一条语句查询当前对象,然后发出n条语句查询关联对象,因此效率变得很低。这里就两个对象,如果有更多的对象,那效率就会大打折扣了,我们该如何解决这个问题呢?
可能大家会想到将fetch设置生fetchtype.lazy就不会发多条语句了,但是这肯定不行,因为设置成lazy后,我们就拿不到account对象了,比较好的解决方法是我们自己写hql语句,使用join fetch。具体看修改后的categoryserviceimpl实现类:

@service("categoryservice") 
public class categoryserviceimpl extends baseserviceimpl<category> implements categoryservice { 
 
  @override 
  public list<category> queryjoinaccount(string type) { 
    string hql = "from category c left join fetch c.account where c.type like :type"; 
    return getsession().createquery(hql) 
        .setstring("type", "%" + type + "%").list(); 
  } 
} 

left join表示关联account一起查询,fetch表示将account对象加到category中去,这样就只会发一条sql语句了,并且返回的category中也包含了account对象了。
3. 完成分页功能
hibernate中的分页很简单,只需要调用两个方法setfirstresult和setmaxresults即可:我们修改一下categoryservice接口和它的实现类categoryserviceimpl:

//categoryservice 
public interface categoryservice extends baseservice<category> { 
  //查询类别信息,级联管理员 
  public list<category> queryjoinaccount(string type, int page, int size); //并实现分页 
} 
 
//categoryserviceimpl 
@service("categoryservice") 
public class categoryserviceimpl extends baseserviceimpl<category> implements categoryservice { 
 
  @override 
  public list<category> queryjoinaccount(string type, int page, int size) { 
    string hql = "from category c left join fetch c.account where c.type like :type"; 
    return getsession().createquery(hql) 
        .setstring("type", "%" + type + "%") 
        .setfirstresult((page-1) * size) //从第几个开始显示 
        .setmaxresults(size) //显示几个 
        .list(); 
  } 
} 

我们在测试类中测试一下:

@runwith(springjunit4classrunner.class) 
@contextconfiguration(locations="classpath:beans.xml") 
public class categoryserviceimpltest { 
 
  @resource 
  private categoryservice categoryservice; 
 
  @test 
  public void testqueryjoinaccount() { 
    for(category c : categoryservice.queryjoinaccount("",1,2)) { //显示第一页,每页2条数据 
      system.out.println(c + "," + c.getaccount()); 
    } 
  } 
} 

为此,我们写完了service的方法了,完成了对商品类别的级联查询和分页功能。
(注:到最后我会提供整个项目的源码下载!欢迎大家收藏或分享)
原文地址:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。