日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

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

發(fā)布時(shí)間:2023/12/20 数据库 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【SSH网上商城项目实战05】完成数据库的级联查询和分页 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ? ? ? 上一節(jié)我們完成了EasyUI菜單的實(shí)現(xiàn)。這一節(jié)我們主要來(lái)寫一下CategoryServiceImpl實(shí)現(xiàn)類,完成數(shù)據(jù)庫(kù)的級(jí)聯(lián)查詢。一般項(xiàng)目從后往前做,先做service(我們沒有抽取Dao,最后再抽取),做完了再做上面層。

??????? 在寫之前,先看一下數(shù)據(jù)庫(kù)中的表的情況:

drop database if exists shop; /*創(chuàng)建數(shù)據(jù)庫(kù),并設(shè)置編碼*/ create database shop default character set utf8; use shop; /*刪除管理員表*/ drop table if exists account; /*刪除商品類別表*/ drop table if exists category; /*============================*/ /* Table:管理員表結(jié)構(gòu) */ /*============================*/ create table account ( /* 管理員編號(hào),自動(dòng)增長(zhǎng) */ id int primary key not null auto_increment, /* 管理員登錄名 */ login varchar(20), /* 管理員姓名 */ name varchar(20), /* 管理員密碼 */ pass varchar(20) ); /*============================*/ /* Table:商品類別表結(jié)構(gòu) */ /*============================*/ create table category ( /* 類別編號(hào),自動(dòng)增長(zhǎng) */ id int primary key not null auto_increment, /* 類別名稱 */ type varchar(20), /* 類別是否為熱點(diǎn)類別,熱點(diǎn)類別才有可能顯示在首頁(yè)*/ hot bool default false, /* 外鍵,此類別由哪位管理員管理 */ account_id int, constraint aid_FK foreign key(account_id) references account(id) );

? ? ? 主要有兩張表,商品類別表和管理員表,并且商品類別表中提供了一個(gè)外鍵關(guān)聯(lián)管理員表。也就是商品和管理員是多對(duì)一的關(guān)系。現(xiàn)在我們開始編寫查詢商品的類別信息,需要級(jí)聯(lián)管理員。

?

1.?實(shí)現(xiàn)級(jí)聯(lián)查詢方法

??????? 首先在CategoryService接口中定義該方法:

public interface CategoryService extends BaseService<Category> { //查詢類別信息,級(jí)聯(lián)管理員 public List<Category> queryJoinAccount(String type); //使用類別的名稱查詢 }

? 然后我們?cè)贑ategoryService的實(shí)現(xiàn)類CategoryServiceImpl中實(shí)現(xiàn)這個(gè)方法:

@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(); } }

? 在兩個(gè)Model中我們配一下關(guān)聯(lián)注解:

//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; }

? ?然后我們?cè)跍y(cè)試類中測(cè)試一下:

@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.?級(jí)聯(lián)查詢存在的問(wèn)題

??????? 我們看一下控制臺(tái)的輸出可以看出,它發(fā)了不止一條SQL語(yǔ)句,但是我們明明只查詢了一次,為什么會(huì)發(fā)這么多語(yǔ)句呢?這就是常見的1+N問(wèn)題。所謂的1+N問(wèn)題,就是首先發(fā)出一條語(yǔ)句查詢當(dāng)前對(duì)象,然后發(fā)出N條語(yǔ)句查詢關(guān)聯(lián)對(duì)象,因此效率變得很低。這里就兩個(gè)對(duì)象,如果有更多的對(duì)象,那效率就會(huì)大打折扣了,我們?cè)撊绾谓鉀Q這個(gè)問(wèn)題呢?

??????? 可能大家會(huì)想到將fetch設(shè)置生FetchType.LAZY就不會(huì)發(fā)多條語(yǔ)句了,但是這肯定不行,因?yàn)樵O(shè)置成LAZY后,我們就拿不到Account對(duì)象了,比較好的解決方法是我們自己寫hql語(yǔ)句,使用join fetch。具體看修改后的CategoryServiceImpl實(shí)現(xiàn)類:

@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表示關(guān)聯(lián)Account一起查詢,fetch表示將Account對(duì)象加到Category中去,這樣就只會(huì)發(fā)一條SQL語(yǔ)句了,并且返回的Category中也包含了Account對(duì)象了。 like:type";需要注意type后面不能有空格。

3.?完成分頁(yè)功能

????????hibernate中的分頁(yè)很簡(jiǎn)單,只需要調(diào)用兩個(gè)方法setFirstResult和setMaxResults即可:我們修改一下CategoryService接口和它的實(shí)現(xiàn)類CategoryServiceImpl:

//CategoryService public interface CategoryService extends BaseService<Category> { //查詢類別信息,級(jí)聯(lián)管理員 public List<Category> queryJoinAccount(String type, int page, int size); //并實(shí)現(xiàn)分頁(yè) } //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) //從第幾個(gè)開始顯示 .setMaxResults(size) //顯示幾個(gè) .list(); } }

我們?cè)跍y(cè)試類中測(cè)試一下:

@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)) { //顯示第一頁(yè),每頁(yè)2條數(shù)據(jù) System.out.println(c + "," + c.getAccount()); } } }

?

本篇可能會(huì)遇到的錯(cuò)誤:

?

org.hibernate.hql.internal.ast.QuerySyntaxException: Category is not mapped [from Category c left join fetch c.account where c.type like :type]

Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Category is not mapped

這個(gè)的原因是 如果已經(jīng)在hibernate.cfg.xml上加上

<mapping class="cn.it.shop.model.Category" />
<mapping class="cn.it.shop.model.Account" />

還是提示無(wú)法映射到 是因?yàn)樵趍odel里面 你需要加上@Entity ?@Table 以及id自增@Id // 表示主鍵?@GeneratedValue

@Column(name = "id", unique = true, nullable = false)和 每個(gè)字段的 @Column (樓主犯錯(cuò)的原因是因?yàn)橐詾槿绻菙?shù)據(jù)庫(kù)有表逆向生成model不需要寫,如果先寫model才需要寫這些@Entity和@Table @column逆向生成表) /*** Category entity. @author MyEclipse Persistence Tools*/@Entity @Table(name="category") public class Category implements java.io.Serializable {private Integer id;private String type;private Boolean hot;private Account account;private Set<Product> products = new HashSet<Product>(0);public Category() {}@Overridepublic String toString() {return "Category [id=" + id + ", type=" + type + ", hot=" + hot+ ", account=" + account + "]";}public Category(Account account, String type, Boolean hot,Set<Product> products) {this.account = account;this.type = type;this.hot = hot;this.products = products;}public Category(Integer id, String type, Boolean hot) {super();this.id = id;this.type = type;this.hot = hot;}public Category(String type, Boolean hot) {super();this.type = type;this.hot = hot;}// Property accessors@Id // 表示主鍵 @GeneratedValue@Column(name = "id", unique = true, nullable = false)public Integer getId() {return this.id;}public void setId(Integer id) {this.id = id;}//多對(duì)一 // @ManyToOne(fetch = FetchType.LAZY)//@ManyToOne(fetch=FetchType.EAGER,cascade=CascadeType.ALL) //急加載,加載一個(gè)實(shí)體時(shí),定義急加載的屬性會(huì)立即從數(shù)據(jù)庫(kù)中加載。@ManyToOne(fetch=FetchType.EAGER)//insert 會(huì)update null問(wèn)題@JoinColumn(name="account_id")//注釋本表中指向另一個(gè)表的外鍵。public Account getAccount(){return this.account;}public void setAccount(Account account) {this.account = account;}@Column(name="type",length = 20)public String getType() {return this.type;}public void setType(String type) {this.type = type;}@Column(name="hot")public Boolean getHot() {return this.hot;}public void setHot(Boolean hot) {this.hot = hot;}

?

總結(jié)

以上是生活随笔為你收集整理的【SSH网上商城项目实战05】完成数据库的级联查询和分页的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。