本文链接:http://www.orlion.ml/28/

一、保存

1、

假设一个group有多个user,一个user只属于一个group,当保存user对象到数据库中时可以

User u = new User();
u.setName("u1");
Group g = new Group();
g.setName("g1");
u.setGroup(g);
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
s.save(g);// 默认hibernate不会帮我们保存
s.save(u);
s.getTransaction().commit();

需要注意hibernate默认不会帮我们保存group对象,应该设置一下。

@ManyToOne有个属性cascade(级联),CascadeType它有

(1)ALL:所有的操作时对当前对象所有级联的对象都会被hibernate操作

(2)MERGE:调用merge()方法时(合并的时候)会进行级联 (MERGE=save+update)

(3)PERSIST:调用persist()方法时(存储的情况下)会进行级联

(4)PEFRESH: 当一个session从数据库中load了一个对象和它级联的对象到内存中,而另外一个session在数据库中对这个对象进行了修改,则hibernate会对第一个sesson load的对象级联的对象刷新操作 (A里面需要读B改过之后的数据)

(5)REMOVE: 删除的情况下会进行级联

(Cascade的属性指明做什么操作的时候关联对象是绑定在一起的)

测试:将User类的getGroup()方法上的@ManyToOne注解修改为@ManyToOne(cascade=(CascadeType.ALL)),然后注释掉上面代码块中s.save(g),运行程序可以发现group会被hibernate自动保存到数据库中。

2、

上面我们存user,关联的group hibernate会帮我们存进去,如果我们存group,关联的user会不会帮我们存进去呢?答:不会

User u1 = new User();
u1.setName("u1");
User u2 = new User();
u1.setName("u2");
User u3 = new User();
u1.setName("u3"); Group g = new Group();
g.setName("g1");
g.getUsers().add(u1);
g.getUsers().add(u2);
g.getUsers().add(u3); Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
s.save(g);//这里如果不设置的话,u1,u2,u3不会自动帮我们存进去
s.getTransaction.commit();

如果想让hibernate帮我们存入group的关联对象需要设置一下:将Group类中的getUsers()方法上的注解@OneToMany(mappedBy="group")修改为@OneToMany(mappedBy="group",cascade=(CascadeType.ALL)),注:如果只这么设置的话,u1,u2,u3存入数据库中后group_id都为NULL,因为u1,u2,u3对象中的group属性是null,所以需要在代码块中加u1.setGroup(g);u2.setGroup(g);u3.setGroup(g)。

规律:(1)多对一关系从多的一方操作比较简单;(2)如果关联关系是双向的,则需要设好导航(mappedBy);(3)双向关系在程序中要设定双向关联

二、读

1、get方式

我们先从数据库中get一个User出来

Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
// 当我们从数据库中将这个对象取出来的时候不管设不设cascade都会把关联的Group对象取出来
User u = (User)s.get(User.class , 1);
s.getTransaction().commit;

我们从数据库中get一个Group出来,不管设不设cascade不会把关联的user取出来,cascade只在存储的时候有效,读取需要再另外设置:

将Group类中的getUsers()方法上注解@OneToMany(mappedBy="group",cascade=(CascadeType.ALL))修改为:@OneToMany(mappedBy="group",cascade=(CascadeType.ALL),fetch=FetchType.EAGER),然后就可以在代码块中写:

Group g = (Group)s.get(Group.class,1);// 如果不加上fetch则不会将关联的User取出来
for(User u : g.getUsers()) {
System.out.println(u.getName());
}

User类中getGroup()方法上注解@ManyToOne默认FetchType是EAGER,因为

当我们从数据库中将这个user对象取出来的时候不管设不设cascade都会把关联的Group对象取出来

当我们将User类中注解@ManyToOne添加属性fetch=FetchType.LAZY时,当我们用到user关联的group时,才会取出来:

Session s = sessionFactory.getCurrentSession();
s.beginTransaction(); User u = (User)s.get(User.class , 1);// 这时不会取出group
System.out.println(u.getGroup().getName());// 这时会取出group s.getTransaction().commit; //System.out.println(u.getGroup().getName());这时会报错no session,原因是session已经关闭了。如果设置为EAGER则不会报错。

FetchType是个枚举类型,有:

(1)EAGER:(渴望)Define that data must be eagerly fetched

(2)LAZY:(懒惰)Define that data can be lazily fetched

2、load方式

三、更新

Session s = sessionFactory.getCurrentSession();
s.beginTransactio();
User u = (User)s.load(User.class , 1);
u.setName("user");
u.getGroup().setName("g");
s.getTransaction().commit();//会发出两条update语句

这样写可以但是我们通常更新的是处于游离状态的对象,而当user处于游离状态时session已经关闭了没法保存。

Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
User u = (User)s.get(User.class,1); s.getTransaction().commit(); u.setName("user");
u.getGroup().setName("group"); Session s2 = sessionFactory.getCurrentSession();
s2.beginTransaction();
s2.update(u);
// 当User类中的getGroup()方法注解@ManyToOne添加属性cascade=CascadeType.ALL时,会更新group,否则当执行update方法时不会update Group
s2.getTransaction().commit();

四、删除

1、删除一个User

Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
User u = (User)s.load(User.class,1);
s.delete(u);
// 这时候会把u删除,然后会把u关联的group对象关联的所有user删除
s.getTransaction().commit();

如果不想把group删除可以:

u.setGroup(null);
s.delete(u);

还可以使用HQL:

Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
s.createQuery("delete from User u where u.id=1");
s.getTransaction().commit();

2、删除Group

Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
Group g = (Group)s.load(Group.class,1);
s.delete(g);
// 这时候会把g删除会把g对象关联的所有user删除(当然已经设置了cascade=all)
s.getTransaction().commit();

如果不想删除所有user,可以把user的group_id设成null。

hibernate(十)双向关联关系的CRUD的更多相关文章

  1. Hibernate映射多对多双向关联关系(小案例)

    多对多双向关联关系(Project(工程)/Emp(员工)为案例): 步骤如下: 1.创建Project类,并需要定义集合类型的Emp属性 public class Project { //编号 pr ...

  2. Hibernate 一对多自身双向关联关系 用于类别表的实现

    分类:一对多自身双向关联关系 Java持久化类: package com.hyy.hibernate.one_to_many.domain; import java.util.HashSet; imp ...

  3. Hibernate关联关系的CRUD

    本文以Group和User(一对多.多对一)双向关联为例,介绍关联关系的CRUD   下面先介绍两个属性 cascade:只影响CRUD中的CUD,即存储(save).更新(update).删除(de ...

  4. Hibernate映射一对多双向关联关系及部门关联属性

    一对多双向关联关系:(Dept/Emp的案例) 既可以根据在查找部门时根据部门去找该部门下的所有员工,又能在检索员工时获取某个员工所属的部门. 步骤如下: 1.构建实体类(部门实体类加set员工集合) ...

  5. Hibernate中双向多对多的两种配置方式

    Hibernate中双向多对多的两种配置方式 1.建立多对多双向关联关系 package cn.happy.entitys; import java.util.HashSet; import java ...

  6. Hibernate一对一双向关联映射

    关键原因在于对象模型具有方向性: 单向:一端只能加载另一端,不能反过来. 双向:两端都可以加载另一端. 问题来了:如何我们想从身份证端(IdCard)加载人(Person),怎么办呢? 下面我们开始介 ...

  7. HIBERNATE一对一双向外键联合主键关联

    HIBERNATE一对一双向外键联合主键关联: 一. 创建主键类:这个主键必须实现serializedable接口和重写其中的hashCode方法和equals方法:为主键类添加一个叫做@Embedd ...

  8. hibernate和mybatis的之CRUD封装差别

    hibernate和mybatis的之CRUD封装差别 以下讲的是基于MVC三层架构. 由于设计架构的差别,hibernate在实际编程中可以把基础的CRUD封装,比如BaseDao类.其它类只要去继 ...

  9. Java进阶知识07 Hibernate一对一双向外键关联(Annotation+XML实现)

    1.Annotation 注解版 1.1.创建Husband类和Wife类 package com.shore.model; import javax.persistence.Entity; impo ...

随机推荐

  1. 浅谈BFC

    Box 是 CSS 布局的对象和基本单位, 直观点来说,就是一个页面是由很多个 Box 组成的.元素的类型和 display属性,决定了这个 Box 的类型. 不同类型的 Box, 会参与不同的 Fo ...

  2. XCode一直显示"scanning for working copies"的解决办法

    一个SVN上的项目,在本地重新CheckOut打开后,一直提示"scanning for working copies"且不能使用SVN的更新.提交等功能,当时想着晾它一晚上,看能 ...

  3. IIS部署ASP.NET常见错误

    今天本地 IIS部署一个.NET Framework 3.5 项目,首先出现一个错误: 静态机制没有办法处理脚本 检查MIME没有问题,检查应用程序池版本,2.0, 果断改成 4.0. 运行之后新错误 ...

  4. 从RAM新建QIcon对象 / Create a QIcon from binary data

    一般,QIcon是通过png或ico等图标文件来初始化的,但是如果图标资源已经在内存里了,或者一个zip压缩文件内,可以通过QPixmap作为桥梁,转换为图标. zf = zipfile.ZipFil ...

  5. chrome插件开发-消息机制中的bug与解决方案

    序言 最近开发chrome插件,涉及到消息传递机时按照教程去敲代码,结果总是不对.研究了大半天终于找到原因,现在记录下. 程序 插件程序参考官网 chrome官网之消息传递机制, 不能FQ的同事也可以 ...

  6. WordPress页面Page和文章Post的相互转换

    1. 进入phpMyAdmin: 2. 进入WordPress对应的数据库: 3. 浏览wp_posts数据表: 4. 找到相应的 页面Page 并编辑(找到相应的 文章Post 并编辑): 5. 修 ...

  7. 配置tomcat编码格式

    tomcat默认编码格式为“ISO-8859-1”,打开tomcat的“server.xml”文件,找到下面行并修改 <Connector connectionTimeout="200 ...

  8. 让你的Android程序更省电

    app主要耗电的原因如下: 1 cpu频繁的运转 -----控制线程 2  大数据量的传输----- 数据压缩传输 3  不停的在网络间切换------------判断网络状体 4 人开发的程序后台都 ...

  9. WebApi Post提交报错 调试无法进入对应action函数

    调试发现有长内容或者是特殊字符就报错,确定是服务端验证的问题 需要 在配置文件 <system.web> 中添加<httpRuntime  requestValidationMode ...

  10. 用UWP实现一个和win10设置页面类似的布局

    不知道有人注意过Win10中的设置页面的布局没?那个页面会根据不同的窗口宽度来调节显示的内容,甚至来后退按钮的操作在不同的宽度也是不同的,看图: 是不是有点cool呢,这篇文章,我们就来做一个类似的布 ...