hibernate关联关系的crud2
hibernate关联关系的CRUD操作,解释都在注释里了,讲了fetchType、cascade。
User类:
package com.oracle.hibernate; import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne; @Entity
public class User { private int id;
private String name;
private Group group; //多对一
@ManyToOne(cascade={CascadeType.ALL}//, //设置级联
//fetch = FetchType.LAZY
)
@JoinColumn(name="groupId")//指定外键名称
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;
} }
Group类:
package com.oracle.hibernate; import java.util.HashSet;
import java.util.Set; import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table; @Entity
@Table(name="t_group")//group是mysql的关键字,换个名
public class Group { private int id;
private String name;
private Set<User> users = new HashSet<User>(); //设置mappedBy和级联
@OneToMany(mappedBy="group",
cascade={CascadeType.ALL}//,//级联管增删改, //fetch=FetchType.EAGER //一的一方默认为LAZY
)
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
@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;
} }
测试类:
package com.oracle.hibernate; import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.AfterClass;
import org.junit.BeforeClass; public class Test { private static SessionFactory sf = null;
@BeforeClass
public static void beforeClass(){ try {
//生成表
new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);
sf = new AnnotationConfiguration().configure().buildSessionFactory();
} catch (HibernateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} @org.junit.Test
public void testSchemaExport(){
new SchemaExport(new AnnotationConfiguration().configure()).create(false, true); }
@AfterClass
public static void afterClass(){
sf.close();
} @org.junit.Test
public void testSaveUser(){ Session s = sf.getCurrentSession();
s.beginTransaction();
User user = new User();
user.setName("u1");
Group g = new Group();
g.setName("g1");
user.setGroup(g);
//s.save(g);默认不会自动保存关联变量,
//设置cascade后,直接保存user就能把user的group也保存
s.save(user);
s.getTransaction().commit();
} @org.junit.Test
public void testSaveGroup(){ Group g = new Group();
g.setName("g1");
User u1 = new User();
u1.setName("u1");
//必须设定User所属的group,否则在保存user时不会保存g的信息(hibernate不知道属于哪个group啊)
u1.setGroup(g);
User u2 = new User();
u2.setName("u2");
u2.setGroup(g);
g.getUsers().add(u1);
g.getUsers().add(u2); Session s = sf.getCurrentSession();
s.beginTransaction(); s.save(g);
s.getTransaction().commit();
} @org.junit.Test
public void testGetUser(){
testSaveGroup();//生成数据 Session s = sf.getCurrentSession();
s.beginTransaction();
/**
* 默认情况,多的一方的fetchType=Eager,这符合正常思维,比如我们取学生时也会把他的老师取出来。
* 设置多的一方User里设fetchType=Lazy时(很少这么干),执行下边的代码发出的sql语句是:
* Hibernate:
select
user0_.id as id2_0_,
user0_.groupId as groupId2_0_,
user0_.name as name2_0_
from
User user0_
where
user0_.id=?
不会把一的一方Group给取出来,只有当用到group的时候(如下边的取u.getGroup.getName)才发sql语句把User和group连接查询
*
*/
User u = (User) s.get(User.class,1);
//取User,默认情况下,不设cascade,也能取出group,这符合平常逻辑。
System.out.println(u.getName()+u.getGroup().getName());
s.getTransaction().commit(); //System.out.println(u.getName()+u.getGroup().getName());
//会报错,因为fetchType为Lazy,用group的时候才发sql语句,而session却关了,所以报错(懒加载错误)
} @org.junit.Test
public void testGetGroup(){
testSaveGroup();//生成数据 Session s = sf.getCurrentSession();
s.beginTransaction();
//取group一方,fetchType默认为Lazy,执行下边的一句话:
//不发取user的sql语句,只发取group的信息的sql。不取多的一方,只有用到user信息时才发sql'语句,下边的g.getUsers()XXX
Group g = (Group) s.get(Group.class,1);
s.getTransaction().commit();
//设置fetchType为EAGER,发的sql语句把user也取出来了,所以即使session关了,也能取出User(从内存)而不报错
System.out.println(g.getName()+g.getUsers());
} @org.junit.Test
public void testLoadUser(){
testSaveGroup();//生成数据 Session s = sf.getCurrentSession();
s.beginTransaction();
//get拿的是User对象,load,拿的是user的代理对象,
//执行下边的代码不会发sql语句,当getGroup时才发sql语句
User u = (User) s.load(User.class,1); //执行此句时先发出sql语句取user,再发sql语句取user和group,发了2条select
System.out.println(u.getName()+u.getGroup().getName());
s.getTransaction().commit(); } @org.junit.Test
public void testUpdateUser1(){
testSaveGroup();//生成数据 Session s = sf.getCurrentSession();
s.beginTransaction();
/**
* 发的sql语句:
* 因为 u.getName()+u.getGroup().getName()既取了u。name,又取了u.的group的name,所以
* 发的select语句取了user和group,
* Hibernate:
select
user0_.id as id2_1_,
user0_.groupId as groupId2_1_,
user0_.name as name2_1_,
group1_.id as id3_0_,
group1_.name as name3_0_
from
User user0_
left outer join
t_group group1_
on user0_.groupId=group1_.id
where
user0_.id=?
//但是为什么还会发出下边的select 语句呢?因为group的fetchType设的EAGER,
* 在u.getGroup().getName()的同时,也会发sql语句去取user的信息。所以不能同时两边设EAGER
* 一般正常人思维去思考:一般:一对多设lazy,多对一设eager。
* 但是假设一个人有多个权限,可以设一对多为eager。公司机构、部门可以用。
Hibernate:
select
users0_.groupId as groupId1_,
users0_.id as id1_,
users0_.id as id2_0_,
users0_.groupId as groupId2_0_,
users0_.name as name2_0_
from
User users0_
where
users0_.groupId=?
* 可以看到先发的select语句取user和group,又取的user()
*/
User u = (User) s.load(User.class,1);
u.setName("user");
u.getGroup().setName("group");
System.out.println(u.getName()+u.getGroup().getName());
s.getTransaction().commit(); } @org.junit.Test
public void testUpdateUser2(){
testSaveGroup();//生成数据 Session s = sf.getCurrentSession();
s.beginTransaction(); User u = (User) s.get(User.class,1);
s.getTransaction().commit();//关闭session,而u已经在内存中。 u.setName("user");//修改user姓名
u.getGroup().setName("group");//修改group Session s2 = sf.getCurrentSession();
s2.beginTransaction();
s2.update(u); //group和user同时更新,user里cascade起的作用
s2.getTransaction().commit(); }
@org.junit.Test
public void testDeleteUser(){
testSaveGroup();//生成表user:u1 u1.group: g u2.group:g group:g Session s = sf.getCurrentSession();
s.beginTransaction();
User u = (User) s.load(User.class, 1);
// 级联:会把u1删掉,再把u1指向的group:g删了,g删了,他所关联的u2也没了。
//s.delete(u);
//解决办法:先解除关联关系,把u的group设成null,再删除
u.setGroup(null);
s.delete(u);
//用hql:
//s.createQuery(" from User u where u.id = 1");
s.getTransaction().commit();
} @org.junit.Test
public void testDeleteGroup(){
testSaveGroup();//生成表user:u1 u1.group: g u2.group:g group:g Session s = sf.getCurrentSession();
s.beginTransaction(); Group g = (Group) s.load(Group.class,1);
//外键指向g的 user 都会被删掉。如果不想删,可以把User的group都设成null,不过这些数据也就成了垃圾数据。
s.delete(g);
s.getTransaction().commit();
}
}
hibernate关联关系的crud2的更多相关文章
- hibernate关联关系笔记
Hibernate关联关系笔记 单向N:1 * 有连接表:在N方使用<join>/<many-to-one>.1方无需配置与之关联的持久化类. * 没有连接表:在N方使用& ...
- Hibernate关联关系映射
1. Hibernate关联关系映射 1.1. one to one <class name="Person"> <id name="id" ...
- Hibernate 关联关系(一对多)
Hibernate 关联关系(一对多) 1. 什么是关联(association) 1.1 关联指的是类之间的引用关系.如果类A与类B关联,那么被引用的类B将被定义为类A的属性.例如: class B ...
- Hibernate关联关系配置(一对多、一对一和多对多)
第一种关联关系:一对多(多对一) "一对多"是最普遍的映射关系,简单来讲就如消费者与订单的关系. 一对多:从消费者角的度来说一个消费者可以有多个订单,即为一对多. 多对一:从订单的 ...
- Hibernate关联关系之双向1—n
•双向 1-n 与双向 n-1 是完全相同的两种情形 •双向 1-n 需要在1的一端可以访问n的一端,反之依然. 测试实例代码: 实体类: package com.elgin.hibernate.nt ...
- Hibernate关联关系之——单向n-1
1 .单向 n-1 关联只需从n的一端可以访问1的一端 2.域模型: 从Order到Customer的多对一单向关联需要在Order类中定义一个Customer属性,而在Customer类中无需定义存 ...
- hibernate关联关系映射详解
词汇解释 关系:事物之间相互作用.相互联系的状态.范围最大. 联系:在关系数据库中表示实体与实体之间的联系,1:1,1:n,m:n. 关联:表示对象之间的关系,既有数量性,又有方向性:动词:将对象之间 ...
- hibernate关联关系映射之配置文件
词汇解释 关系:事物之间相互作用.相互联系的状态.范围最大. 联系:在关系数据库中表示实体与实体之间的联系,1:1,1:n,m:n. 关联:表示对象之间的关系,既有数量性,又有方向性:动词:将对象之间 ...
- Hibernate关联关系之多对多
多对多映射关系 建立多对多单向关联关系 创建Employee类: public class Employee { private Integer empid; //员工编号 private Strin ...
随机推荐
- (字符串 KMP)Blue Jeans -- POJ -- 3080:
链接: http://poj.org/problem?id=3080 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=88230#probl ...
- 匹配yyyy-mm-dd日期格式的的正则表达式[转]
转http://www.jb51.net/article/28034.htm 今天头让我修改个javascript方法,验证输入的日期是否符合要求.恩.我们的要求是yyyy-mm-dd这样的格式,其他 ...
- Mixin模式
Mixin是JavaScript中用的最普遍的模式,几乎所有流行类库都会有Mixin的实现. Mixin是掺合,混合,糅合的意思,即可以就任意一个对象的全部或部分属性拷贝到另一个对象上. 从提供的接口 ...
- iOS设备抓包终极解决方案(支持https)
http://bbs.chinapyg.com/forum.php?mod=viewthread&tid=74423&extra=page%3D1%26filter%3Dtypeid% ...
- SQL Server查询所有存储过程信息、触发器、索引
1. [代码]查询所有存储过程 01 select Pr_Name as [存储过程], [参数]=stuff((select ','+[Parameter] 02 from ( 03 se ...
- OpenglEs开篇
1.,但博客有接近一年没有写了.虽然有学到东西,但没有记录感觉是是空空的,最近在学习Opengles, 现在开始重操旧业(写博客了).
- C# 时间戳与DateTime间的互相转换
//DateTime转换为时间戳public long GetTimeSpan(DateTime time) { DateTime startTime = TimeZone.CurrentTimeZo ...
- 磁盘 blk_update_request: I/O error
1.尝试1: 解决 blk_update_request: I/O error, dev fd0, sector 0 错误 参考文档: https://bbs.archlinux.org/viewto ...
- ADB 源码分析(一) ——ADB模块简述【转】
ADB源码分析(一)——ADB模块简述 1.Adb 源码路径(system/core/adb). 2.要想很快的了解一个模块的基本情况,最直接的就是查看该模块的Android.mk文件,下面就来看看a ...
- Spring 中aop切面注解实现
spring中aop的注解实现方式简单实例 上篇中我们讲到spring的xml实现,这里我们讲讲使用注解如何实现aop呢.前面已经讲过aop的简单理解了,这里就不在赘述了. 注解方式实现aop我们 ...