轉自:http://blog.csdn.net/eson_15/article/details/51320212
上一節我們完成了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)
- );
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); //使用類別的名稱查詢
- }
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();
- }
- }
@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;
- }
//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());
- }
- }
- }
@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();
- }
- }
@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();
- }
- }
//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());
- }
- }
- }
@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的方法了,完成了對商品類別的級聯查詢和分頁功能。相關閱讀:http://blog.csdn.net/column/details/str2hiberspring.html
整個項目的源碼下載地址:http://blog.csdn.net/eson_15/article/details/51479994
_____________________________________________________________________________________________________________________________________________________
-----樂於分享,共同進步!
- 頂
- 9
- 踩
- 1
我的同類文章
- •【SSH網上商城項目實戰29】使用JsChart技術在後臺顯示商品銷售報表2016-05-26
- •【SSH網上商城項目實戰27】域名空間的申請和項目的部署及發佈2016-05-23
- •【SSH網上商城項目實戰26】完成訂單支付後的短信發送功能2016-05-22
- •【SSH網上商城項目實戰24】Struts2中如何處理多個Model請求2016-05-21
- •【SSH網上商城項目實戰22】獲取銀行圖標以及支付頁面的顯示2016-05-19
- •【SSH網上商城項目實戰20】在線支付平臺的介紹2016-05-18
- •【SSH網上商城項目實戰28】使用Ajax技術局部更新商品數量和總價2016-05-24
- •【SSH網上商城項目實戰30】項目總結(附源碼下載地址)2016-05-27
- •【SSH網上商城項目實戰25】使用java email給用戶發送郵件2016-05-22
- •【SSH網上商城項目實戰23】完成在線支付功能2016-05-20
- •【SSH網上商城項目實戰21】從Demo中看易寶支付的流程2016-05-18