Hibernate中关联关系的CRUD(增删改查)

关联关系的CRUD(增删改查)

一、增加数据

1、User和Group的关联关系:User对Group是Many-To-One,Group对User是One-To-Many

2、默认情况下,不会自动保存尚未保存关联的对象。因为对象没有保存的情况下,对象是Transient状态,此时数据库中并没有存储,所以获取不到该对象。

3、使用级联cascade方式可以自动将关联的对象进行存储。其取值有ALL,PERSIST,REFRESH,REMOVE,DETACH,MERGE这几种取值。其中,ALL表示在任何情况下进行级联操作。PERSIST表示持久化的时候进行级联。

3、实验1(只保存User对象的情况下,自动保存Group)

Group.java

package com.zgy.hibernate.model;

import java.util.HashSet;

import java.util.Set;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.JoinColumn;

import javax.persistence.OneToMany;

import javax.persistence.Table;

@Entity

@Table(name="t_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;

}

}

4、User.java

package com.zgy.hibernate.model;

import javax.persistence.CascadeType;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.JoinColumn;

import javax.persistence.ManyToOne;

import javax.persistence.Table;

@Entity

@Table(name="t_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(cascade={CascadeType.ALL})

public Group getGroup() {

return group;

}

public void setGroup(Group group) {

this.group = group;

}

}

5、JUnit测试

package com.zgy.hibernate.model;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

import org.hibernate.cfg.Configuration;

import org.hibernate.service.ServiceRegistry;

import org.hibernate.tool.hbm2ddl.SchemaExport;

import org.junit.AfterClass;

import org.junit.BeforeClass;

import org.junit.Test;

public class ORMapppingTest {

public static SessionFactory sf = null;

@BeforeClass

public static void beforeClass(){

Configuration configure =new Configuration().configure();

new SchemaExport(configure).create(true, true);

sf = configure.buildSessionFactory();

}

@Test

public void testSaveUser() {

User user = new User();

user.setName("user1");

Group group = new Group();

group.setName("group");

user.setGroup(group);

Session s = sf.openSession();

s.beginTransaction();

//s.save(group);

s.save(user);

s.getTransaction().commit();

}

@AfterClass

public static void afterClass(){

sf.close();

}

}

6、结果:

(1)不保存group的情况下,运行JUnit会报错

(2)在User.java中加入@ManyToOne(cascade={CascadeType.ALL}),那么再次运行JUnit时将不会再报错。

(3)查看生成的sql语句:

Hibernate: create table t_group (id integer not null auto_increment, name varchar(255), primary key (id))

Hibernate: create table t_user (id integer not null auto_increment, name varchar(255), group_id integer, primary key (id))

Hibernate: alter table t_user add constraint FK_e5f24mh6aryt9hsy99oydps6g foreign key (group_id) references t_group (id)

Hibernate: insert into t_group (name) values (?)

Hibernate: insert into t_user (group_id, name) values (?, ?)

7、实验2(仅保存Group对象的情况下,自动保存User)

(1)修改Group.java

package com.zgy.hibernate.model;

import java.util.HashSet;

import java.util.Set;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.JoinColumn;

import javax.persistence.OneToMany;

import javax.persistence.Table;

import javax.persistence.CascadeType;

@Entity

@Table(name="t_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",

cascade={CascadeType.ALL}

)

public Set<User> getUsers() {

return users;

}

public void setUsers(Set<User> users) {

this.users = users;

}

}

(2)去除User.java中加入的cascade={CascadeType.ALL}这段Annotation

package com.zgy.hibernate.model;

import javax.persistence.CascadeType;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.JoinColumn;

import javax.persistence.ManyToOne;

import javax.persistence.Table;

@Entity

@Table(name="t_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;

}

}

(3)测试

要建立User和Group两者的双向关系,并且只保存Group对象

package com.zgy.hibernate.model;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

import org.hibernate.cfg.Configuration;

import org.hibernate.service.ServiceRegistry;

import org.hibernate.tool.hbm2ddl.SchemaExport;

import org.junit.AfterClass;

import org.junit.BeforeClass;

import org.junit.Test;

public class ORMapppingTest {

public static SessionFactory sf = null;

@BeforeClass

public static void beforeClass(){

Configuration configure =new Configuration().configure();

new SchemaExport(configure).create(true, true);

sf = configure.buildSessionFactory();

}

@Test

public void testSaveUser() {

User user1 = new User();

user1.setName("user1");

User user2 = new User();

user2.setName("user2");

Group group = new Group();

group.setName("group1");

group.getUsers().add(user1);

group.getUsers().add(user2);

user1.setGroup(group);

user2.setGroup(group);

Session s = sf.openSession();

s.beginTransaction();

s.save(group);

//s.save(user);

s.getTransaction().commit();

}

@AfterClass

public static void afterClass(){

sf.close();

}

}

(4)观察结果

生成的SQL语句:

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),

group_id integer,

primary key (id)

)

alter table t_user

add constraint FK_e5f24mh6aryt9hsy99oydps6g

foreign key (group_id)

references t_group (id)

查看数据库中的信息:

select * from t_group;

select * from t_user;

数据保存成功。

8.双向关系在程序中要设置双向关联

9.双向关系要使用mappedBy

二、读取数据

还是一上面的例子做说明

1、读取User数据,是否能读取Group中的数据?

2、ManyToOne默认的情况下是可以取出One里的数据的,也就是说,获取User对象的数据的时候,是可以获取Group对象中的数据的。

3、读取Group数据的时候,是否能读取User中的数据?

4、cascade并不会影响读取,fetch管理读取

5、fetch的属性是Enum类型,分别为LAZY,EAGER。取值为LAZY时,不会获取User中的数据;取值为EAGER时,可以获取User的数据

6、JPA接口默认为一对多为Lazy,多对一为Eager,但是Hibernate反向工程生成Entity时,多对一为Lazy,需要手动改为Eager。

7、实验:

8、Group.java

package com.zgy.hibernate.model;

import java.util.HashSet;

import java.util.Set;

import javax.persistence.Entity;

import javax.persistence.FetchType;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.JoinColumn;

import javax.persistence.OneToMany;

import javax.persistence.Table;

import javax.persistence.CascadeType;

@Entity

@Table(name="t_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",

cascade={CascadeType.ALL},

fetch=FetchType.EAGER

)

public Set<User> getUsers() {

return users;

}

public void setUsers(Set<User> users) {

this.users = users;

}

}

9、User.java

package com.zgy.hibernate.model;

import javax.persistence.CascadeType;

import javax.persistence.Entity;

import javax.persistence.FetchType;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.ManyToOne;

import javax.persistence.Table;

@Entity

@Table(name="t_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(cascade={CascadeType.ALL},

fetch=FetchType.LAZY

)

public Group getGroup() {

return group;

}

public void setGroup(Group group) {

this.group = group;

}

}

10、JUnit测试

@Test

public void testGetUser() {

testSaveGroup();

Session s = sf.openSession();

s.beginTransaction();

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

s.getTransaction().commit();

}

@Test

public void testGetGroup() {

testSaveGroup();

Session s = sf.openSession();

s.beginTransaction();

Group g = (Group)s.get(Group.class, 1);

s.getTransaction().commit();

for(User u : g.getUsers()){

System.out.println(u.getName());

}

}

11、结论

(1)将User设置为@ManyToOne(cascade={CascadeType.ALL},fetch=FetchType.LAZY的时候,将不再取得Group的属性。在session关闭前,如果使用到Group属性还是可以手动取得。Session关闭后将去得到Group的属性。

(2)@ManyToOne(cascade={CascadeType.ALL},fetch=FetchType.LAZY的时候,先取出的是User,再取出的是两者之间的关系。

Hibernate: select user0_.id as id1_1_0_, user0_.group_id as group_id3_1_0_, user0_.name as name2_1_0_ from t_user user0_ where user0_.id=?

Hibernate: select group0_.id as id1_0_0_, group0_.name as name2_0_0_, users1_.group_id as group_id3_0_1_, users1_.id as id1_1_1_, users1_.id as id1_1_2_, users1_.group_id as group_id3_1_2_, users1_.name as name2_1_2_ from t_group group0_ left outer join t_user users1_ on group0_.id=users1_.group_id where group0_.id=?

(3)@ManyToOne(cascade={CascadeType.ALL},fetch=FetchType.EAGER的时候,先取出的是关系,然后取出的是User

Hibernate: select user0_.id as id1_1_0_, user0_.group_id as group_id3_1_0_, user0_.name as name2_1_0_, group1_.id as id1_0_1_, group1_.name as name2_0_1_ from t_user user0_ left outer join t_group group1_ on user0_.group_id=group1_.id where user0_.id=?

Hibernate: select users0_.group_id as group_id3_0_0_, users0_.id as id1_1_0_, users0_.id as id1_1_1_, users0_.group_id as group_id3_1_1_, users0_.name as name2_1_1_ from t_user users0_ where users0_.group_id=?

(4)两边都设置EAGER的时候,会发出两次select语句。所以,一般是在一遍设置EAGER就可以了。

三、更新数据

1.cascade={CascadeType.ALL}的时候,默认会级联。因此在修改User属性的时候,会修改Group的属性。例如:

@Test

public void testUpdateUser() {

testSaveGroup();

Session s = sf.openSession();

s.beginTransaction();

User u = (User)s.load(User.class, 1);

u.setName("user");

u.getGroup().setName("ggg");

s.getTransaction().commit();

}

此处修改了Group的name属性,因此,在更新User对象的时候,会更新Group对象的属性。

如下SQL语句说明了以上观点:

Hibernate: update t_user set group_id=?, name=? where id=?

Hibernate: update t_group set name=? where id=?

2.在User.java中,配置cascade={CascadeType.MERGE},此时在JUnit中,使用merge()方法后,将会产生级联,即只保存User对象的情况下,会自动保存Group对象。使用merge()来合并两个session中的同一对象。

以下是JUnit中的测试方法

@Test

public void testUpdateUser() {

testSaveGroup();

Session s = sf.getCurrentSession();

s.beginTransaction();

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

s.getTransaction().commit();

u.setName("u");

u.getGroup().setName("g");

Session s2 = sf.getCurrentSession();

s2.beginTransaction();

s2.merge(u);

s2.getTransaction().commit();

}

同理,设置cascade的值的时候,在session中使用对应的方法将可以实现级联操作。

四、删除数据

1、ORMapping编程模型:

|映射模型

|以Hibernate为例

|jpa annotation

|Hibernate annotation extension

|Hibernate xml

|jpa xml

|接口编程

|jpa编程接口

|Hibernate

2、@Test

public void testDeleteUser() {

testSaveGroup();

Session s = sf.openSession();

s.beginTransaction();

User u = (User)s.load(User.class, 1);

s.delete(u);

s.getTransaction().commit();

}

如下的测试方法会删除User和Group中的所有数据。原因是因为两者是级联关系。User.java中设置的@ManyToOne(cascade={CascadeType.ALL},Group.java中设置的是@OneToMany(mappedBy="group",

cascade={CascadeType.ALL},所以删除User的时候会关联到该User对象的Group属性,从而删除该Group属性,而Group属性又关联了User属性,所以又会删除User的内容,从而导致了删除了两张表中的全部内容。

3.解决如上的问题的方法是消除关联关系,再进行删除。

@Test

public void testDeleteUser() {

testSaveGroup();

Session s = sf.openSession();

s.beginTransaction();

User u = (User)s.load(User.class, 1);

u.setGroup(null);

s.delete(u);

s.getTransaction().commit();

}

查看生成的SQL语句:

Hibernate: delete from t_user where id=?

还有一种方式就是使用HQL语句:

s.createQuery("delete from User where u.id = 1").executeUpdate();

也可以达到效果。

4.想要消除关联关系,先设定关系为null,在删除对应的记录。如果不删除记录,那么该记录就会变为垃圾数据。

时间: 2024-08-08 09:32:43

Hibernate中关联关系的CRUD(增删改查)的相关文章

【框架】[Hibernate]利用Hibernate进行单表的增删改查-Web实例

转载请注明出处:http://blog.csdn.net/qq_26525215 本文源自[大学之旅_谙忆的博客] 前面两篇博客已经将Hibernate的基础知识讲解得差不多了,差不多到写实例的时候了. 本篇只用hibernate进行单表的增删改查. 应用Hibernate,对students表进行增删改查. service层和DAO层,我都是直接写实现类了(因为这里主要是演示一下Hibernate的使用),如果是开发项目,注意一定要写接口! 准备数据库: 首先准备一个students表: cr

android中SQLite数据库的增删改查

1.数据库帮助类PersonSQLiteOpenHelper package com.wzw.sqllitedemo.db; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper

asp.net中利用JSON进行增删改查中运用到的方法

//asp.net中 利用JSON进行操作, //增加: //当点击"增加链接的时候",弹出增加信息窗口,然后,在窗体中输入完整信息,点击提交按钮. //这里我们需要考虑这些:我会进行异步提交,使用jquery中的方法,$.post("网页名",JSON,callback); //JSON的写法:{"name":name,"id":id},那我们对其进行假设,比方说,表单中的textbox很多,需要我们填写的信息 //也很多,

用CI框架向数据库中实现简单的增删改查

以下代码基于CodeIgniter_2.1.3版 用PHP向数据库中实现简单的增删改查(纯代码)请戳 http://www.cnblogs.com/corvoh/p/4641476.html CodeIgniter_2.1.3与PHP5.6的兼容问题请戳 http://www.cnblogs.com/corvoh/p/4649357.html 增: //insert//语法:$bool=$this->db->insert('表名',关联数组); $data=array( 'username'=

用PHP向数据库中实现简单的增删改查(纯代码,待完善)

<?php $con = mysql_connect("localhost:3306","root",""); if (!$con) { die('Could not connect: ' . mysql_error()); } mysql_select_db("test", $con); $result = mysql_query("SELECT * FROM user"); echo "

在ASP.NET MVC4中实现同页面增删改查,无弹出框02,增删改查界面设计

在上一篇"在ASP.NET MVC4中实现同页面增删改查,无弹出框01,Repository的搭建"中,已经搭建好了Repository层,本篇就剩下增删改查的界面了......今天的阳光真特么好,写完本篇,好出去在阳光下溜溜狗.散散步什么的,正所谓文武之道一张一弛,走神了,进入正题. 首先是一个View Model,在这里定义验证规则,提交和保存数据的时候还必须和领域模型映射. using System; using System.ComponentModel.DataAnnotat

SAP云平台以微服务的方式提供了Document的CRUD(增删改查)操作。该微服务基于标准的CMI

SAP云平台以微服务的方式提供了Document的CRUD(增删改查)操作.该微服务基于标准的CMIS协议(Content Management Interoperability Service). 同标准的CMIS相比,SAP云平台的Document Service增添了一些功能的支持: 通过一个Hello World应用来了解如何在Java程序里消费SAP云平台的Document Service. 通过这个链接下载例子程序. 点击该超链接下载Java Web Tomcat 8 SDK. 例子

前端的CRUD增删改查的小例子

前端的CRUD增删改查的小例子 1.效果演示 2.相关代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> *{ margin: 0; padding: 0; } .box{ width: 300px; margin: 0 auto; } ul{

Hibernate之API初识及增删改查实现

声明:关于hibernate的学习.非常大一部分东西都是概念性的. 大家最好手里都有一份学习资料,在我的博文中.我不会把书本上的概念一类的东西搬过来.那没有不论什么意义.关于hibernate的学习,我主要是通过演示项目让大家加深一些概念的理解,同一时候,也是为了让大家深层次的理解hibernate.而不仅仅是单纯的停留在概念上,假设仅仅是单纯的理解一些概念性的东西.到最后你们肯定会一无所获.并且过段时间就会忘记.所以以后的hibernate的学习.希望大家多看下演示项目.下载下来部署上演示看看