【03】SSH练习——hibernate的级联和1+n问题
来源:互联网 发布:淘宝页面改版 编辑:程序博客网 时间:2024/05/11 18:50
1、数据库表设计
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) );2、在entity中用注解配置级联关系
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "account")public Set<Category> getCategories() {return this.categories;}@ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "account_id")public Account getAccount() {return this.account;}
3、在service中添加一个方法用于测试
import java.util.List;import org.springframework.stereotype.Service;import com.cqb.bean.Category;@Service("categoryService")public class CategoryServiceImp extends BaseServiceImp<Category> implements CategoryService {@Overridepublic List<Category> queryJoinAccount(String type) {// TODO Auto-generated method stub//String hql = "from Category c where c.type like :type";String hql = "from Category c left join fetch c.account where c.type like :type";return getSession().createQuery(hql).setString("type", "%"+type+"%").list();}}
4、用Junit测试
import java.util.Date;import javax.annotation.Resource;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.cqb.bean.Category;import com.cqb.service.CategoryService;import com.cqb.service.CategoryServiceImp;@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations="classpath:beans.xml") public class SSHTest { /*@Resourceprivate CategoryService categoryService; @Resource private Date date; public void setCategoryService(CategoryService categoryService) {this.categoryService = categoryService;} public CategoryService getCategoryService() {return categoryService;} @Test //测试Spring IOC的开发环境 public void springIoc() { System.out.println(date); } @Test //测试Hibernate的开发环境,因为没有整合,可以直接new public void hihernate() { Category category = categoryService.get(1); category.setType("chenqingb"); categoryService.update(category); System.out.println("hahahahaha"); } */@Resource private CategoryService categoryService; @Test public void testQueryJoinAccount() { for(Category c : categoryService.queryJoinAccount("")) { System.out.println(c); System.out.println(c.getAccount()); } } }
控制台信息:
Hibernate: select category0_.id as id1_1_, category0_.account_id as account_4_1_, category0_.hot as hot2_1_, category0_.type as type3_1_ from test.category category0_ where category0_.type like ?
Hibernate: select account0_.id as id1_0_0_, account0_.login as login2_0_0_, account0_.name as name3_0_0_, account0_.pass as pass4_0_0_ from test.account account0_ where account0_.id=?
com.cqb.bean.Category@7b60c3e
com.cqb.bean.Account@3bcd426c
发现出现了两条hql语句(数据库中category表和account表各只有一条信息 所以此处1+n 为1+1)
由此 我们开始研究hibernate的抓取策略
1+N问题也可以叫N+1问题,什么是1+N问题呢?
如果在一个对象里关联另一个对象,并且fetch = FetchType.EAGER。
比如说ManyToOne(OneToMany也存在这种问题)关联,本来只需要取Many里的对象属性,可是Many里关联的对象都会单独再发一条语句取关联对象的属性。
本来只用发一条就可以查出Many里的对象属性,可是它发了一条语句后,再发N条语句取关联对象的数据。
解决办法:
1、 设置多的那方的FetchType为LAZY :在合适的时候才发出语句(按需要发语句)。
2、BatchSize:在One对象设置Size后,取出Many里的数据后,再发N/Size条语句取关联对象的数据,从而达到少发语句的目的。(----不能彻底解决~)
3、使用Join Fetch:(使用Criteria或者写HQL语句时在后面加上left join fetch w.category)将Many与One做外连接,因此只要发一条语句就可以查出Many与其相关联的One对象数据,Criteria默认就是这种做法。
如何选择解决办法:
如果只要用Many里的对象,不用关联对象的属性,那就用方法1解决;
如果要Many里的对象属性,也想要关联的对象属性就用方法3解决。
在本次测试中 需要获取关联对象account 若在account中设置未lazy 则取不出account 所以用第三种方案
import java.util.List;import org.springframework.stereotype.Service;import com.cqb.bean.Category;@Service("categoryService")public class CategoryServiceImp extends BaseServiceImp<Category> implements CategoryService {@Overridepublic List<Category> queryJoinAccount(String type) {// TODO Auto-generated method stub//String hql = "from Category c where c.type like :type";String hql = "from Category c left join fetch c.account where c.type like :type";return getSession().createQuery(hql).setString("type", "%"+type+"%").list();}}
控制台信息:
Hibernate: select category0_.id as id1_1_0_, account1_.id as id1_0_1_, category0_.account_id as account_4_1_0_, category0_.hot as hot2_1_0_, category0_.type as type3_1_0_, account1_.login as login2_0_1_, account1_.name as name3_0_1_, account1_.pass as pass4_0_1_ from test.category category0_ left outer join test.account account1_ on category0_.account_id=account1_.id where category0_.type like ?
com.cqb.bean.Category@15723761
com.cqb.bean.Account@65327f5
- 【03】SSH练习——hibernate的级联和1+n问题
- SSH之hibernate—1和n的关联映射
- MyBatis级联第四篇——N+1问题和全局延迟加载【推荐,MyBatis级联重要的一篇原创,建议认真读】
- Hibernate中的1+N问题(带级联查询条件的情况)
- hibernate 级联删除的问题
- Hibernate的1+N问题(N+1)
- Hibernate的N+1问题
- Hibernate的n+1问题
- hibernate 的N + 1问题
- Hibernate——1+N问题
- Hibernate——1+N问题
- Hibernate的Cascade——级联操作
- hibernate级联查询执行n+1次sqlt语句问题(内含解决办法,优化方式)
- Hibernate的n+1问题和基本映射总结
- 笔记---Hibernate的“N+1”问题和一级缓存
- 【02】SSH练习——BaseService中泛型的问题
- SSH级联删除问题
- SSH框架之Hibernate的inverse属性、cascade级联操作
- 枚举法(穷举法)
- 阶乘后面0的数量
- RAC 预安装DNS报 prvf-5636 错误
- webpack+vue.js 搭建
- oracle中的分析函数
- 【03】SSH练习——hibernate的级联和1+n问题
- 21.运行时环境
- Logistic_Regression
- UnrealVS扩展
- 杭电--4548 美素数
- springmvc报错 org.springframework.web.servlet.DispatcherServlet
- PrepareStatement 如何打印真实 SQL
- 0415
- 【服务器】nginx安装和配置