首页 > 代码库 > Hibernate中关联关系的CRUD(增删改查)

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

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

一、增加数据

1、UserGroup的关联关系:UserGroupMany-To-OneGroupUserOne-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(truetrue);

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)测试

要建立UserGroup两者的双向关系,并且只保存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(truetrue);

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();

}

此处修改了Groupname属性,因此,在更新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();

}

如下的测试方法会删除UserGroup中的所有数据。原因是因为两者是级联关系。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,在删除对应的记录。如果不删除记录,那么该记录就会变为垃圾数据。


技术分享

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