本文以Group和User(一对多、多对一)双向关联为例,介绍关联关系的CRUD

 

下面先介绍两个属性

cascade:只影响CRUD中的CUD,即存储(save)、更新(update)、删除(delete)

fetch:只影响CRUD中的R,即读取(get、load)

 

cascade(级联):

此属性仅仅帮助我们简化编程,不是必选项

如果A和B为单向关联,则在主导方设置cascade属性

如果A和B为双向关联,则在双方都要设置cascade属性

如果两个对象之间有关联关系,比如User和Group多对一关联

如果想要保存User的时候自动保存Group,可在User类的@ManyToOne注解中设置cascade(级联)属性

反过来,如果想要保存Group的时候自动保存User,可在Group类的@OneToMany注解中设置cascade(级联)属性

 

对于User(多方)和Group(一方)

执行如下语句

User u = (User) session.get(User.class, 1);

在取出多方对象u的同时也会把一方对象对应属性取出来,这是@ManyToOne的默认设置.相当于设置@ManyToOne(fetch=FetchType.EAGER)

反过来,取一方对象的时候,则不会把多方对象取出

若想要在取出一方对象g的同时取出多方对象,则应在Group类的@OneToMany注解中设置fetch属性
@OneToMany注解中fetch的默认值为FetchType.LAZY, 相当于设置@OneToMany(fetch=FetchType.LAZY) 

fetch的取值有两个

fetch=FetchType.EAGER :执行语句就取出

fetch=FetchType.LAZY :用的时候才取出

两者的区别类似于get和load的区别

注意:对于双向关联,不要两边都设EAGER(会有多余的查询语句发出),可以都设LAZY

一般是多对一设置EAGER,一对多设置LAZY

 

建Group实体类和User实体类,以及Junit测试类

@Entity
@Table(name="_group")
public class Group {
private int id;
private String name;
private Set<User> users = new HashSet<User>();
@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="_user")
public class User {
private int id;
private String name;
private 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;
}
@ManyToOne
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
}

 

public class ORMappingTest {

	private static SessionFactory sf = null;

	@BeforeClass
public static void beforeClass(){
sf = new Configuration().configure().buildSessionFactory();
} @AfterClass
public static void afterClass(){
sf.close();
} @Test
public void test() { //下面将会完善此test()方法 }
}

 

接下来开始CRUD的练习

首先在Group类和User类的@OneToMany和@ManyToOne注解中添加cascade属性

//Group类    此处fetch属性中,LAZY为默认值,故也可不写
@OneToMany(mappedBy="group",cascade={CascadeType.ALL},fetch=FetchType.LAZY)
public Set<User> getUsers() {
return users;
}

 

//User类    此处fetch属性中,EAGER为默认值,故也可不写
@ManyToOne(cascade={CascadeType.ALL},fetch=FetchType.EAGER)
public Group getGroup() {
return group;
}

 

然后,完善Junit测试类的test()方法

 

CRUD----C   增   session.save()

1.保存User对象的同时自动保存Group对象

@Test
public void test() {
Session session = sf.getCurrentSession();
session.beginTransaction(); Group g = new Group();
g.setName("lisi"); User u = new User();
u.setName("user1");
u.setGroup(g); session.save(u); //因为在User类的@ManyToOne注解中设置了cascade(级联)属性,故只需保存User对象即可,Group对象会自动保存 session.getTransaction().commit();
}

2.保存Group对象的同时自动保存User对象

@Test
public void test() {
Session session = sf.getCurrentSession();
session.beginTransaction(); User u1 = new User();
User u2 = new User(); Group g = new Group(); u1.setName("user1");
u1.setGroup(g);
u2.setName("user2");
u2.setGroup(g); g.setName("group1");
g.getUsers().add(u1);
g.getUsers().add(u2); session.save(g); //因为在Group类的@OneToMany注解中设置了cascade(级联)属性,故只需保存Group对象即可,User对象会自动保存 session.getTransaction().commit();
}

 

CRUD----R   查   session.get()和session.load()

1.取出User对象的同时取出Group对象

@Test
public void test() { Session session = sf.getCurrentSession();
session.beginTransaction(); User u = (User) session.get(User.class, 1); //在取出多方对象u的同时也会把一方对象对应属性取出来,这是@ManyToOne的默认设置
System.out.println(u.getGroup().getName()); //打印输出_group表中对应的name值 session.getTransaction().commit();
}

2.取出Group对象的同时取出User对象

@Test
public void test() { Session session = sf.getCurrentSession();
session.beginTransaction(); Group g = (Group) session.get(Group.class, 2); //在取出一方对象g的同时取出多方对象,此时应在Group类的@OneToMany注解中设置fetch属性
for(User u : g.getUsers()){
System.out.println(u.getId()+","+u.getName()); //打印输出_user表中的相关数据
} session.getTransaction().commit();
}

CRUD----U   改   session.update()

通过取出的User对象,既可以更改User对象中的属性名字,也可以更改与其级联的Group对象中的属性名字

@Test
public void test { Session session = sf.getCurrentSession();
session.beginTransaction(); User u = (User) session.get(User.class, 3); //在取出多方对象u的同时也会把一方对象对应属性取出来,这是@ManyToOne的默认设置
u.setName("name"); //更改User对象中的属性名字
u.getGroup().setName("Groupname"); //也可以更改与其级联的Group对象中的属性名字
session.update(u); session.getTransaction().commit();
}

CRUD----D   删   session.delete()

删除User表中的某一条记录

两种方式,如下:

@Test
public void testDelete() { Session session = sf.getCurrentSession();
session.beginTransaction(); //删除User表中id值为1的记录
User u = (User) session.get(User.class, 1); //在取出多方对象u的同时也会把一方对象对应属性取出来,这是@ManyToOne的默认设置
u.setGroup(null); //应该先消除关联关系,再删除对应记录
session.delete(u); //如果直接删除,由于设置了cascade属性,则会删除Group和User中相关的所有数据 //删除User表中id值为2的记录
session.createQuery("delete from User u where u.id=2").executeUpdate(); session.getTransaction().commit();
}

Hibernate关联关系的CRUD的更多相关文章

  1. hibernate关联关系的crud之级联

    cascade级联,只会影响CRUD的CUD,不会影响读取.不设置级联,从多的一方能读出一的一方,设了级联,从一的一方,默认也不能读出多的一方. 如果两个对象之间有关联,不管是一对多,多对一,单向还是 ...

  2. hibernate关联关系的crud2

    hibernate关联关系的CRUD操作,解释都在注释里了,讲了fetchType.cascade. User类: package com.oracle.hibernate; import javax ...

  3. hibernate关联关系笔记

    Hibernate关联关系笔记 单向N:1 *  有连接表:在N方使用<join>/<many-to-one>.1方无需配置与之关联的持久化类. *  没有连接表:在N方使用& ...

  4. Hibernate关联关系映射

    1.  Hibernate关联关系映射 1.1.  one to one <class name="Person"> <id name="id" ...

  5. Hibernate 关联关系(一对多)

    Hibernate 关联关系(一对多) 1. 什么是关联(association) 1.1 关联指的是类之间的引用关系.如果类A与类B关联,那么被引用的类B将被定义为类A的属性.例如: class B ...

  6. hibernate(十)双向关联关系的CRUD

    本文链接:http://www.orlion.ml/28/ 一.保存 1. 假设一个group有多个user,一个user只属于一个group,当保存user对象到数据库中时可以 User u = n ...

  7. 关联关系的CRUD

    关联关系中的CRUD_Cascade_Fetch 1. hibernate_1700_one2many_many2one_bi_crud 2. 设定 cascade 可以设定在持久化时对于关联对象的操 ...

  8. Hibernate关联关系配置(一对多、一对一和多对多)

    第一种关联关系:一对多(多对一) "一对多"是最普遍的映射关系,简单来讲就如消费者与订单的关系. 一对多:从消费者角的度来说一个消费者可以有多个订单,即为一对多. 多对一:从订单的 ...

  9. Hibernate关联关系之双向1—n

    •双向 1-n 与双向 n-1 是完全相同的两种情形 •双向 1-n 需要在1的一端可以访问n的一端,反之依然. 测试实例代码: 实体类: package com.elgin.hibernate.nt ...

随机推荐

  1. lcd中像素深度bpp和像素格式(比如RGB,YUV)的关系

    像素深度(bits per pixel,简称bpp) 一个像素的颜色在计算机中由多少个字节数据来描述.计算机中用二进制位来表示一个像素的数据,用来表示一个像素的数据位越多,则这个像素的颜色值更加丰富. ...

  2. CSS学习(二)- 有关 hasLayout 和 BFC

    1. hasLayout 概念说明 ‘Layout’ 可以被某些 CSS property(特性)不可逆的触发,而某些 HTML 元素本身就具有 layout . ‘Layout’ 在 IE 中可以通 ...

  3. [已解决]windows下python3.x与python2.7共存版本pip使用报错问题

    > 由于最近要更新插件,突然发现没法使用pip来安装升级插件,查了一圈才找到解决办法,特记录在此,便于其它人查询. 报错信息如下: Fatal error in launcher: Unable ...

  4. SlidingMenu官方实例分析2——BaseActivity

    本文从BaseActivity说起,因为其他功能页面都继承了这个类. 这里继承了Sliding中的SlidingFragmentActivity,其实也可以继承SlidingActivity, 但是现 ...

  5. 圆角头像----CSS3特效

    w3c:http://www.w3school.com.cn/cssref/pr_border-radius.asp 定义和用法 border-radius 属性是一个简写属性,用于设置四个 bord ...

  6. GetWindowText 卡死的一种可能的原因

    最近一个项目中碰到GetWindowText经常卡死的问题,这个项目有多个线程,检查代码发现发生死锁的是一个数据线程和一个UI线程. 示意图大致如下(data thread和UI thread在同一个 ...

  7. Laravel5.1 路由 -路由分组

    路由分组有啥好处? 有时候啊 一大堆路由它们都有共同的地方,比如都使用一个中间件(过两天写)或是前缀都一样,避免代码重复 我们可以将他们分到一组中. 1 路由分组可以共享哪些属性? 中间件 middl ...

  8. Linux 的字符串截取很有用。有八种方法。

    假设有变量 var=http://www.aaa.com/123.htm 1. # 号截取,删除左边字符,保留右边字符. echo ${var#*//} 其中 var 是变量名,# 号是运算符,*// ...

  9. sql duplicate key

    本文来自:高爽,转载请注明. 向数据库插入记录时,有时会有这种需求,当符合某种条件的数据存在时,去修改它,不存在时,则新增,也就是saveOrUpdate操作.这种控制可以放在业务层,也可以放在数据库 ...

  10. <2013 08 20> -----澳大利亚博士研究生申请-----

    1.澳大利亚昆士兰大学博士的申请一年中什么时间都可以,但奖学金的评选每年只有四轮.和美国不同的是,在提交申请材料之前,个人必须联系好愿意接收你的导师,这个可以自己套磁联系,也可以和那边学院的小秘联系, ...