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,在删除对应的记录。如果不删除记录,那么该记录就会变为垃圾数据。



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是有关使用Spring Boot实现CRUD操作的增加、删除、修询的一些基本步骤: 1. 配置项目依赖 在您的Maven或Gradle构建文件添加Spring Boot和相关的数据库依赖。例如,如果您想要使用MySQL数据库,则需要添加以下依赖项: ```xml <!-- Spring Boot --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- MySQL database driver --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- Spring Data JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> ``` 2. 配置数据库连接 在application.properties或application.yml文件添加数据库连接信息,如下所示: ```yaml spring.datasource.url=jdbc:mysql://localhost:3306/yourdatabase spring.datasource.username=yourusername spring.datasource.password=yourpassword spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=update ``` 3. 创建实体类 创建一个实体类来表示您要持久化的数据。例如,如果您要创建一个用户对象,则可以编写以下代码: ```java @Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "name") private String name; @Column(name = "email") private String email; // getter and setter methods } ``` 4. 创建Repository接口 创建一个Repository接口来定义CRUD操作。例如,如果您要操作用户对象,则可以编写以下代码: ```java @Repository public interface UserRepository extends JpaRepository<User, Long> { } ``` 5. 创建服务类 创建一个服务类来实现您的业务逻辑。例如,如果您要实现用户管理功能,则可以编写以下代码: ```java @Service public class UserService { @Autowired private UserRepository userRepository; public List<User> getAllUsers() { return userRepository.findAll(); } public User getUserById(Long id) { return userRepository.findById(id).orElse(null); } public User addUser(User user) { return userRepository.save(user); } public User updateUser(User user) { return userRepository.save(user); } public void deleteUserById(Long id) { userRepository.deleteById(id); } } ``` 6. 创建控制器类 创建一个控制器类来处理HTTP请求。例如,如果您要处理用户对象的HTTP请求,则可以编写以下代码: ```java @RestController @RequestMapping("/api/users") public class UserController { @Autowired private UserService userService; @GetMapping("") public List<User> getAllUsers() { return userService.getAllUsers(); } @GetMapping("/{id}") public User getUserById(@PathVariable("id") Long id) { return userService.getUserById(id); } @PostMapping("") public User addUser(@RequestBody User user) { return userService.addUser(user); } @PutMapping("") public User updateUser(@RequestBody User user) { return userService.updateUser(user); } @DeleteMapping("/{id}") public void好的,我可以用文回答您关于 Spring Boot CRUD 的问题。 Spring Boot 是一个基于 Spring 框架的快速开发框架,可以帮助开发者快速构建 Web 应用程序。CRUD 则是指对于一个数据实体,可以进行增加(Create)、询(Retrieve)、更新(Update)、删除(Delete)的操作。 在 Spring Boot 实现 CRUD 操作,通常需要以下步骤: 1. 定义数据实体类:首先需要定义一个数据实体类,表示要进行 CRUD 操作的数据对象。该类需要使用 JPA 注解来定义实体和属性,并且需要定义一个主键属性。 2. 定义数据访问层接口:接下来需要定义一个数据访问层接口,用于定义数据操作的方法,包括增加、询、更新和删除等操作。 3. 实现数据访问层接口:在实现数据访问层接口时,需要使用 Spring Data JPA 提供的 Repository 接口,该接口提供了许多 CRUD 操作的默认实现,可以大大减少我们的代码量。 4. 定义业务逻辑层接口和实现类:在定义业务逻辑层接口和实现类时,可以将数据访问层接口作为一个成员变量注入进来,并在业务逻辑层方法调用数据访问层接口的方法,来完成具体的数据操作。 5. 定义控制器类:最后需要定义一个控制器类,用于接收 HTTP 请求,并将请求参数传递给业务逻辑层进行处理,然后返回相应的结果给客户端。 以上就是实现 Spring Boot CRUD 的基本步骤,具体实现过程可以参考 Spring Boot 官方文档和相关教程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值