转自:https://blog.csdn.net/eson_15/article/details/51320212

上一节我们完成了EasyUI菜单的实现。这一节我们主要来写一下CategoryServiceImpl实现类,完成数据库的级联查询。一般项目从后往前做,先做service(我们没有抽取Dao,最后再抽取),做完了再做上面层。

在写之前,先看一下数据库中的表的情况:

 1 drop database if exists shop;
2 /*创建数据库,并设置编码*/
3 create database shop default character set utf8;
4
5 use shop;
6 /*删除管理员表*/
7 drop table if exists account;
8 /*删除商品类别表*/
9 drop table if exists category;
10
11 /*============================*/
12 /* Table:管理员表结构 */
13 /*============================*/
14 create table account
15 (
16 /* 管理员编号,自动增长 */
17 id int primary key not null auto_increment,
18 /* 管理员登录名 */
19 login varchar(20),
20 /* 管理员姓名 */
21 name varchar(20),
22 /* 管理员密码 */
23 pass varchar(20)
24 );
25
26 /*============================*/
27 /* Table:商品类别表结构 */
28 /*============================*/
29 create table category
30 (
31 /* 类别编号,自动增长 */
32 id int primary key not null auto_increment,
33 /* 类别名称 */
34 type varchar(20),
35 /* 类别是否为热点类别,热点类别才有可能显示在首页*/
36 hot bool default false,
37 /* 外键,此类别由哪位管理员管理 */
38 account_id int,
39 constraint aid_FK foreign key(account_id) references account(id)
40 );

主要有两张表,商品类别表和管理员表,并且商品类别表中提供了一个外键关联管理员表。也就是商品和管理员是多对一的关系。现在我们开始编写查询商品的类别信息,需要级联管理员。

1. 实现级联查询方法
        首先在CategoryService接口中定义该方法:

 1 public interface CategoryService extends BaseService<Category> {
2 //查询类别信息,级联管理员
3 public List<Category> queryJoinAccount(String type); //使用类别的名称查询
4 }
5 然后我们在CategoryService的实现类CategoryServiceImpl中实现这个方法:
6
7
8
9
10
11 @Service("categoryService")
12 public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService {
13
14 @Override
15 public List<Category> queryJoinAccount(String type) {
16 String hql = "from Category c where c.type like :type";
17 return getSession().createQuery(hql)
18 .setString("type", "%" + type + "%").list();
19 }
20 }

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

//Category类中

  1 package cn.it.shop.model;
2
3 import java.util.Set;
4
5 import javax.persistence.Column;
6 import javax.persistence.Entity;
7 import javax.persistence.FetchType;
8 import javax.persistence.GeneratedValue;
9 import javax.persistence.Id;
10 import javax.persistence.JoinColumn;
11 import javax.persistence.ManyToOne;
12
13
14 /**
15 * Category entity. @author MyEclipse Persistence Tools
16 */
17 @Entity
18 public class Category implements java.io.Serializable {
19
20 // Fields
21
22 private Integer id;
23 private Account account;
24 private String type;
25 private Boolean hot;
26 // private Set<Product> products = new HashSet<Product>(0);
27
28
29 // Constructors
30
31 /** default constructor */
32 public Category() {
33 }
34
35 @Override
36 public String toString() {
37 return "Category [id=" + id + ", account=" + account + ", type=" + type
38 + ", hot=" + hot + "]";
39 }
40
41 /** full constructor */
42 public Category(Account account, String type, Boolean hot,
43 Set<Product> products) {
44 this.account = account;
45 this.type = type;
46 this.hot = hot;
47 // this.products = products;
48 }
49
50 public Category(Integer id, String type, Boolean hot) {
51 super();
52 this.id = id;
53 this.type = type;
54 this.hot = hot;
55 }
56
57 public Category(String type, Boolean hot) {
58 super();
59 this.type = type;
60 this.hot = hot;
61 }
62
63 // Property accessors
64 @Id
65 @GeneratedValue
66 @Column(name = "id", unique = true, nullable = false)
67 public Integer getId() {
68 return this.id;
69 }
70
71 public void setId(Integer id) {
72 this.id = id;
73 }
74
75 @ManyToOne(fetch = FetchType.LAZY)
76 @JoinColumn(name = "aid")
77 public Account getAccount() {
78 return this.account;
79 }
80
81 public void setAccount(Account account) {
82 this.account = account;
83 }
84
85 @Column(name = "type", length = 20)
86 public String getType() {
87 return this.type;
88 }
89
90 public void setType(String type) {
91 this.type = type;
92 }
93
94 @Column(name = "hot")
95 public Boolean getHot() {
96 return this.hot;
97 }
98
99 public void setHot(Boolean hot) {
100 this.hot = hot;
101 }
102
103 // @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "category")
104 // public Set<Product> getProducts() {
105 // return this.products;
106 // }
107 //
108 // public void setProducts(Set<Product> products) {
109 // this.products = products;
110 // }
111
112 }

//Account类中

  1 package cn.it.shop.model;
2
3 import java.util.HashSet;
4 import java.util.Set;
5
6 import javax.persistence.CascadeType;
7 import javax.persistence.Column;
8 import javax.persistence.Entity;
9 import javax.persistence.FetchType;
10 import javax.persistence.GeneratedValue;
11 import javax.persistence.Id;
12 import javax.persistence.OneToMany;
13 import javax.persistence.Table;
14
15 /**
16 * Account entity. @author MyEclipse Persistence Tools
17 */
18 @Entity
19 public class Account implements java.io.Serializable {
20
21 // Fields
22
23 private Integer id;
24 private String login;
25 private String name;
26 private String pass;
27 // private Set<Category> categories = new HashSet<Category>(0);
28
29
30 // Constructors
31
32 /** default constructor */
33 public Account() {
34 }
35
36 @Override
37 public String toString() {
38 return "Account [id=" + id + ", login=" + login + ", name=" + name
39 + ", pass=" + pass + "]";
40 }
41
42 /** full constructor */
43 public Account(String login, String name, String pass,
44 Set<Category> categories) {
45 this.login = login;
46 this.name = name;
47 this.pass = pass;
48 // this.categories = categories;
49 }
50
51
52 public Account(String login, String name, String pass) {
53 super();
54 this.login = login;
55 this.name = name;
56 this.pass = pass;
57 }
58
59 // Property accessors
60 @Id
61 @GeneratedValue
62 @Column(name = "id", unique = true, nullable = false)
63 public Integer getId() {
64 return this.id;
65 }
66
67 public void setId(Integer id) {
68 this.id = id;
69 }
70
71 @Column(name = "login", length = 20)
72 public String getLogin() {
73 return this.login;
74 }
75
76 public void setLogin(String login) {
77 this.login = login;
78 }
79
80 @Column(name = "name", length = 20)
81 public String getName() {
82 return this.name;
83 }
84
85 public void setName(String name) {
86 this.name = name;
87 }
88
89 @Column(name = "pass", length = 20)
90 public String getPass() {
91 return this.pass;
92 }
93
94 public void setPass(String pass) {
95 this.pass = pass;
96 }
97
98 // @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "account")
99 // public Set<Category> getCategories() {
100 // return this.categories;
101 // }
102 //
103 // public void setCategories(Set<Category> categories) {
104 // this.categories = categories;
105 // }
106
107 }

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

 1 @RunWith(SpringJUnit4ClassRunner.class)
2 @ContextConfiguration(locations="classpath:beans.xml")
3 public class CategoryServiceImplTest {
4
5 @Resource
6 private CategoryService categoryService;
7
8 @Test
9 public void testQueryJoinAccount() {
10 for(Category c : categoryService.queryJoinAccount("")) {
11 System.out.println(c);
12 System.out.println(c.getAccount());
13 }
14 }
15 }

2. 级联查询存在的问题
        我们看一下控制台的输出可以看出,它发了不止一条SQL语句,但是我们明明只查询了一次,为什么会发这么多语句呢?这就是常见的1+N问题。所谓的1+N问题,就是首先发出一条语句查询当前对象,然后发出N条语句查询关联对象,因此效率变得很低。这里就两个对象,如果有更多的对象,那效率就会大打折扣了,我们该如何解决这个问题呢?

可能大家会想到将fetch设置生FetchType.LAZY就不会发多条语句了,但是这肯定不行,因为设置成LAZY后,我们就拿不到Account对象了,比较好的解决方法是我们自己写hql语句,使用join fetch。具体看修改后的CategoryServiceImpl实现类:

 1 @Service("categoryService")
2 public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService {
3
4 @Override
5 public List<Category> queryJoinAccount(String type) {
6 String hql = "from Category c left join fetch c.account where c.type like :type";
7 return getSession().createQuery(hql)
8 .setString("type", "%" + type + "%").list();
9 }
10 }

left join表示关联Account一起查询,fetch表示将Account对象加到Category中去,这样就只会发一条SQL语句了,并且返回的Category中也包含了Account对象了。

3. 完成分页功能
        Hibernate中的分页很简单,只需要调用两个方法setFirstResult和setMaxResults即可:我们修改一下CategoryService接口和它的实现类CategoryServiceImpl:

 1 //CategoryService
2 public interface CategoryService extends BaseService<Category> {
3 //查询类别信息,级联管理员
4 public List<Category> queryJoinAccount(String type, int page, int size); //并实现分页
5 }
6
7 //CategoryServiceImpl
8 @Service("categoryService")
9 public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService {
10
11 @Override
12 public List<Category> queryJoinAccount(String type, int page, int size) {
13 String hql = "from Category c left join fetch c.account where c.type like :type";
14 return getSession().createQuery(hql)
15 .setString("type", "%" + type + "%")
16 .setFirstResult((page-1) * size) //从第几个开始显示
17 .setMaxResults(size) //显示几个
18 .list();
19 }
20 }

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

 1 @RunWith(SpringJUnit4ClassRunner.class)
2 @ContextConfiguration(locations="classpath:beans.xml")
3 public class CategoryServiceImplTest {
4
5 @Resource
6 private CategoryService categoryService;
7
8 @Test
9 public void testQueryJoinAccount() {
10 for(Category c : categoryService.queryJoinAccount("",1,2)) { //显示第一页,每页2条数据
11 System.out.println(c + "," + c.getAccount());
12 }
13 }
14 }

为此,我们写完了Service的方法了,完成了对商品类别的级联查询和分页功能。

【SSH网上商城项目实战05】完成数据库的级联查询和分页的更多相关文章

  1. 【SSH网上商城项目实战30】项目总结

      转自:https://blog.csdn.net/eson_15/article/details/51479994 0. 写在前面 项目基本完成了,加上这个总结,与这个项目相关的博客也写了30篇了 ...

  2. 【SSH网上商城项目实战30】项目总结(附源码下载地址)

    项目基本完成了,加上这个总结,与这个项目相关的博客也写了30篇了,积少成多,写博客的过程是固化思路的一个过程,对自己很有用,同时也能帮助别人.顺便说个题外话,在学习的过程中肯定会遇到很多异常出现,我们 ...

  3. 【SSH网上商城项目实战27】域名空间的申请和项目的部署及发布

     转自:https://blog.csdn.net/wwww_com/article/details/54405355 前面陆陆续续的完成了网上商城的一些基本功能,虽然还有很多地方有待完善,但是不影响 ...

  4. 【SSH网上商城项目实战16】Hibernate的二级缓存处理首页的热门显示

    转自:https://blog.csdn.net/eson_15/article/details/51405911 网上商城首页都有热门商品,那么这些商品的点击率是很高的,当用户点击某个热门商品后需要 ...

  5. 【SSH网上商城项目实战21】从Demo中看易宝支付的流程

         转自: https://blog.csdn.net/eson_15/article/details/51447492 这一节我们先写一个简单点的Demo来测试易宝支付的流程,熟悉这个流程后, ...

  6. 【SSH网上商城项目实战01】整合Struts2、Hibernate4.3和Spring4.2

    转自:https://blog.csdn.net/eson_15/article/details/51277324 今天开始做一个网上商城的项目,首先从搭建环境开始,一步步整合S2SH.这篇博文主要总 ...

  7. 【SSH网上商城项目实战25】使用java email给用户发送邮件

       转自: https://blog.csdn.net/eson_15/article/details/51475046 当用户购买完商品后,我们应该向用户发送一封邮件,告诉他订单已生成之类的信息, ...

  8. 【SSH网上商城项目实战15】线程、定时器同步首页数据(类似于博客定期更新排名)

    转自:https://blog.csdn.net/eson_15/article/details/51387378 上一节我们做完了首页UI界面,但是有个问题:如果我在后台添加了一个商品,那么我必须重 ...

  9. 【SSH网上商城项目实战14】商城首页UI的设计

    转自:https://blog.csdn.net/eson_15/article/details/51373403 前面我们利用EasyUI和SSH搭建好了后台的基本框架,做好了后台的基本功能,包括对 ...

随机推荐

  1. 设置视口中心点setViewCenter

    ads_point pt; ads_name ent,ss; //切换到模型空间 acedMspace(); if (RTNORM != acedGetPoint(NULL,_T("\n选择 ...

  2. 为解决Samba windows 无法访问 尝试过的方法

    1, 通过   vi /etc/sysconfig/selinux 把 SELINUX=enforcing   修改为SELINUX= disable 退出保存,并且重启.(设置了) 2, 把wind ...

  3. tf入门-卷积步长strides参数的具体解释

    conv1 = tf.nn.conv2d(input_tensor,conv1_weights,strides=[1,1,1,1],padding='SAME') 这是一个常见的卷积操作,其中stri ...

  4. jquery中的$()详解

    一.jQuery的三种$() $号是jQuery“类”的一个别称,$()构造了一个jQuery对象.所以,“$()”可以叫做jQuery的构造函数. 1.$()可以是$(expresion),即css ...

  5. 利用python 学习数据分析 (学习四)

    内容学习自: Python for Data Analysis, 2nd Edition         就是这本 纯英文学的很累,对不对取决于百度翻译了 前情提要: 各种方法贴: https://w ...

  6. delphi 10.2 ---treeview 基本用法

    unit Unit2; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...

  7. QuantLib 金融计算——数学工具之数值积分

    目录 QuantLib 金融计算--数学工具之数值积分 概述 常见积分方法 高斯积分 如果未做特别说明,文中的程序都是 Python3 代码. QuantLib 金融计算--数学工具之数值积分 载入模 ...

  8. C#生成验证码类

    using System;using System.Collections.Generic;using System.Drawing;using System.Drawing.Drawing2D;us ...

  9. Java NIO学习与记录(七): Reactor单线程模型的实现

    Reactor单线程模型的实现 一.Selector&Channel 写这个模型需要提前了解Selector以及Channel,之前记录过FileChannel,除此之外还有以下几种Chann ...

  10. Mac 10.12安装FTP工具FileZilla

    说明:在Windows估计用的比较多,在Linux基本不用了,CRT和Xshell基本可以完成上传. 下载: (链接: https://pan.baidu.com/s/1bpaxmeN 密码: uuw ...