hibernate注解(三)1+N问题
一。什么时候会遇到1+N的问题?
前提:Hibernate默认表与表的关联方法是fetch="select",不是fetch="join",这都是为了懒加载而准备的。
1)一对多(<set><list>) ,在1的这方,通过1条sql查找得到了1个对象,由于关联的存在 ,那么又需要将这个对象关联的集合取出,所以合集数量是n还要发出n条sql,于是本来的1条sql查询变成了1 +n条 。
2)多对一<many-to-one> ,在多的这方,通过1条sql查询得到了n个对象,由于关联的存在,也会将这n个对象对应的1 方的对象取出, 于是本来的1条sql查询变成了1 +n条 。
3)iterator 查询时,一定先去缓存中找(1条sql查集合,只查出ID),在没命中时,会再按ID到库中逐一查找, 产生1+n条SQL
二。怎么解决1+N 问题?
1 )lazy=true, hibernate3开始已经默认是lazy=true了;lazy=true时不会立刻查询关联对象,只有当需要关联对象(访问其属性,非id字段)时才会发生查询动作。
2)使用二级缓存, 二级缓存的应用将不怕1+N 问题,因为即使第一次查询很慢(未命中),以后查询直接缓存命中也是很快的。刚好又利用了1+N 。
3) 当然你也可以设定fetch="join",一次关联表全查出来,但失去了懒加载的特性。
三。示例
1.两张表
create table t_group (
id integer not null auto_increment,
name varchar(255),
primary key (id)
)
create table t_user (
id integer not null auto_increment,
name varchar(255),
myGroup integer,
primary key (id)
)
alter table t_user
add index FKCB63CCB6D4A4BEC0 (myGroup),
add constraint FKCB63CCB6D4A4BEC0
foreign key (myGroup)
references t_group (id)
2.代码如下:
@Entity
@Table(name="t_group")
public class Group {
private int id;
private String name; private Set<User> users = new HashSet<User>();
public Group(){ }
public Group(String name) {
this.name = name;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToMany(mappedBy="group")
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}
@Entity
@Table(name="t_user")
public class User {
private int id;
private String name;
private Group group; public User(){ }
public User(String name) {
this.name = name;
} @ManyToOne
@JoinColumn(name="myGroup")
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3.数据如下
4.默认情况下
@Test
public void getAllUser(){
Session session = sf.openSession();
Transaction tx =session.beginTransaction();
List<User> groups = session.createQuery("from User").list(); //只要一条语句就可以取出全部内容。但hibernate默认会把关联的Group也取出来。
String string = "---------------------------- "; //由于每个user都不同group,所以会发出N条语句查询group.
//本例会发出1+10条
for(User g : groups){
string += g.getName();
}
System.out.println(string);
tx.commit();
session.close();
}
5.解决:
(1).在User类中标注group----fetch=FetchType.LAZY
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="myGroup")
public Group getGroup() {
return group;
}
(2).在Group类中写---------@BatchSize(size=10)
@Entity
@Table(name="t_group")
@BatchSize(size=10)
public class Group {}
(3)使用连接查询
List<User> groups = session.createQuery("from User u left join fetch u.group g").list();
注意:group是属性名,而不是数据库字段名。 不然出错
6.实验花絮:
@Test
public void saveGroupAndUser2(){
Session session = sf.openSession();
Transaction tx =session.beginTransaction(); for(int i=1; i<=10; i++) {
Group g= new Group();
g.setName("g"+i);
session.save(g); User u = new User();
u.setName("u"+i);
u.setGroup(g);
session.save(u);
} tx.commit();
session.close();
}
参考下面的代码,上面红色字体的session.save(g)可以省略.不然org.hibernate.TransientObjectException: object references an unsaved transient instance
在User类中
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="myGroup")
public Group getGroup() {
return group;
}
hibernate注解(三)1+N问题的更多相关文章
- Hibernate注解映射联合主键的三种主要方式
今天在做项目的时候,一个中间表没有主键,所有在创建实体的时候也未加组件,结果报以下错误: org.springframework.beans.factory.BeanCreationException ...
- Hibernate注解----类级别注解以及属性注解详解----图片版本
这篇文章是我在慕课网上学习Hibernate注解的时候进行手机以及整理的笔记. 今天把它分享给大家,希望对大家有用.可以进行收藏,然后需要的时候进行对照一下即可.这样能起到一个查阅的作用. 本文主要讲 ...
- Hibernate注解配置
在之前的第一次对框架的实际应用中,我使用的是Hibernate的xml配置方法,xml配置方法非常繁琐, 还是推荐所有使用Hibernate的人使用注解方式进行配置,在这篇文章中,我将列举出我们常用的 ...
- Hibernate注解使用以及Spring整合
Hibernate注解使用以及Spring整合 原文转自:http://wanqiufeng.blog.51cto.com/409430/484739 (1) 简介: 在过去几年里,Hibernate ...
- 【maven + hibernate(注解) +spring +springMVC】 使用maven搭建项目
研究,百度,查资料+好友帮助,使用MyEcplise2015工具,通过maven搭建hibernate+springMVC+spring的项目,数据库采用MySql5.5 不过使用的版本会在项目搭建过 ...
- [Hibernate] 注解映射例子
Hibernate 注解(Hibernate Annotation) 是一种比较新的方式,通过在 java 简单类增加注解,来声明 java 类和数据库表的映射,作用和 xml 文件相似.hibern ...
- Hibernate注解与JPA
Hibernate注解与JPA - charming的专栏 - CSDN博客http://blog.csdn.net/zxc123e/article/details/51499652 之前记录的一些东 ...
- Hibernate注解开发、注解创建索引
1.注解的目的 简化繁琐的ORM映射文件(*.hbm)的配置 2.JPA和hibernate的关系 JPA:java persistence API,JPA注解是JavaEE的标准和规范. 两者的关系 ...
- hibernate 注解 联合主键映射
联合主键用Hibernate注解映射方式主要有三种: 第一.将联合主键的字段单独放在一个类中,该类需要实现java.io.Serializable接口并重写equals和hascode,再将 该类注解 ...
- Hibernate学习一:Hibernate注解CascadeType
http://zy19982004.iteye.com/blog/1721846 ———————————————————————————————————————————————————————— Hi ...
随机推荐
- React Native(五)——获取设备信息react-native-device-info
心酸史: 自从接触rn开始后,越来越多的引入第三方组件而开始的配置文件,让自己一再头疼: 明明是按照官方文档一步一步的配置,为什么别人可以做到的自己却屡屡出错,真是哭笑不得--从微信分享react-n ...
- Java中遍历字符串toCharArray()和charAt()效率比较
public static void test() { String s = "a"; for(int i = 0; i < 100000; i++) { s += &quo ...
- 老徐FrankXuLei 受邀为花旗银行讲授《微软WCF服务分布式开发与SOA架构设计课程》
老徐FrankXuLei 受邀为花旗银行上海研发中心讲授<微软WCF服务分布式开发与SOA架构设计课程> 受邀为花旗银行上海研发中心讲授<微软WCF服务分布式开发与SOA架构设计课程 ...
- 【转】java:Session(会话)机制详解
书中讲:以下情况,Session结束生命周期,Servlet容器将Session所占资源释放:1.客户端关闭浏览器2.Session过期3.服务器端调用了HttpSession的invalidate( ...
- 【转】strlen源码
strlen源码剖析 学习高效编程的有效途径之一就是阅读高手写的源代码,CRT(C/C++ Runtime Library)作为底层的函数库,实现必然高效.恰好手中就有glibc和VC的CRT源代码, ...
- div里粘贴文字后,移动光标至最后
cursormanager.js //Namespace management idea from http://enterprisejquery.com/2010/10/how-good-c-hab ...
- MAC升级node及npm
清除node.js的cache: sudo npm cache clean -f 安装 n 工具,这个工具是专门用来管理node.js版本的,别怀疑这个工具的名字,是他是他就是他,他的名字就是 &qu ...
- 生产环境mysql的参数设置不一样,好好的程序,又出错
一.概述 报错信息如下: org.springframework.jdbc.BadSqlGrammarException: ### Error querying database. Cause: c ...
- Android 音视频同步(A/V Sync)
1. 音视频同步原理 1)时间戳 音视频同步主要用于在音视频流的播放过程中,让同一时刻录制的声音和图像在播放的时候尽可能的在同一个时间输出. 解决音视频同步问题的最佳方案就是时间戳:首先选择一个参考 ...
- html处理富文本内容,避免XSS工具类
import org.apache.commons.lang3.StringEscapeUtils;import org.jsoup.Jsoup;import org.jsoup.safety.Whi ...