Spring Data JPA多对多双向Map

x33g5p2x  于2022-10-14 转载在 Spring  
字(6.8k)|赞(0)|评价(0)|浏览(933)

在本教程中,我们将学习如何使用SpringDataJPA(Hibernate as JPA提供者)实现多对多域模型双向Map。
我们使用UserRole实体执行多对多双向Map。
双向关系Map允许您在两个方向上导航关联。
在双向Map中,我们在两个实体(用户和角色)上使用@ManyToMany注解。

多对多双向Map-ER图

多对多关系是使用名为users_roles的第三个表实现的,该表包含用户和角色表的外键。

1.创建Spring Boot项目

SpringBoot提供了一个名为https://start.spring.io的web工具来快速引导应用程序。只需转到https://start.spring.io并生成一个新的spring-boot项目。

在创建Spring引导时使用以下详细信息:
**项目名称:**Spring Data jpa课程
**项目类型:**Maven
**选择依赖项:**Spring Data JPA、MySQL Driver、Lombok
**软件包名称:**net.javaguides.springboot

2.Maven依赖项

这是完整的pom。xml供您参考:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.6.1</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>net.javaguides</groupId>
  12. <artifactId>spring-data-jpa-course</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>spring-data-jpa-course</name>
  15. <description>Demo project for Spring Boot</description>
  16. <properties>
  17. <java.version>11</java.version>
  18. </properties>
  19. <dependencies>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-data-jpa</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>mysql</groupId>
  26. <artifactId>mysql-connector-java</artifactId>
  27. <scope>runtime</scope>
  28. </dependency>
  29. <dependency>
  30. <groupId>org.springframework.boot</groupId>
  31. <artifactId>spring-boot-starter-test</artifactId>
  32. <scope>test</scope>
  33. </dependency>
  34. </dependencies>
  35. <build>
  36. <plugins>
  37. <plugin>
  38. <groupId>org.springframework.boot</groupId>
  39. <artifactId>spring-boot-maven-plugin</artifactId>
  40. </plugin>
  41. </plugins>
  42. </build>
  43. </project>

3.配置MySQL数据库

在本例中,让我们使用MySQL数据库存储和检索数据,并使用Hibernate属性创建和删除表。

打开应用程序。属性文件,并向其中添加以下配置:

  1. spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false
  2. spring.datasource.username=root
  3. spring.datasource.password=Mysql@123
  4. spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
  5. spring.jpa.hibernate.ddl-auto = create-drop

确保在运行Spring引导应用程序之前创建一个演示数据库。
此外,根据您机器上的MySQL安装更改MySQL用户名和密码。

4.创建JPA实体

让我们在基本包“net.javaguides.springboot”中创建一个实体包。
在实体包中,创建包含以下内容的User和Role类:

User.java

  1. package com.springdatajpa.springboot.entity;
  2. import lombok.Getter;
  3. import lombok.Setter;
  4. import javax.persistence.*;
  5. import java.util.HashSet;
  6. import java.util.Set;
  7. @Getter
  8. @Setter
  9. @Entity
  10. @Table(
  11. name = "users",
  12. uniqueConstraints = @UniqueConstraint(
  13. name = "unique_email",
  14. columnNames = "email"
  15. )
  16. )
  17. public class User {
  18. @Id
  19. @GeneratedValue(strategy = GenerationType.IDENTITY)
  20. private long id;
  21. private String firstName;
  22. private String lastName;
  23. private String email;
  24. private String password;
  25. @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
  26. @JoinTable(
  27. name = "users_roles",
  28. joinColumns = @JoinColumn(
  29. name = "user_id", referencedColumnName = "id"
  30. ),
  31. inverseJoinColumns = @JoinColumn(
  32. name = "role_id", referencedColumnName = "id"
  33. )
  34. )
  35. private Set<Role> roles = new HashSet<>();
  36. }

Role.java

  1. package com.springdatajpa.springboot.entity;
  2. import lombok.Getter;
  3. import lombok.Setter;
  4. import javax.persistence.*;
  5. import java.util.HashSet;
  6. import java.util.Set;
  7. @Getter
  8. @Setter
  9. @Entity
  10. @Table(name = "roles")
  11. public class Role {
  12. @Id
  13. @GeneratedValue(strategy = GenerationType.IDENTITY)
  14. private long id;
  15. private String name;
  16. @ManyToMany(cascade = {
  17. CascadeType.PERSIST,
  18. CascadeType.MERGE
  19. }, fetch = FetchType.EAGER,
  20. mappedBy = "roles")
  21. private Set<User> users = new HashSet<>();
  22. }

5.创建Spring Data JPA存储库

接下来,让我们创建SpringDataJPA存储库,以从数据库访问User和Role实体。

JpaRepository接口定义了实体上所有CRUD操作的方法,以及名为SimpleJpaReproository的JpaRepocitory的默认实现。
让我们在基本包“net.javaguides.springdatarest”中创建一个存储库包。
在存储库软件包中,创建具有以下内容的UserRepository和RoleRestory界面:

UserRepository.java

  1. package com.springdatajpa.springboot.repository;
  2. import com.springdatajpa.springboot.entity.User;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. public interface UserRepository extends JpaRepository<User, Long> {
  5. }

RoleRepository.java

  1. package com.springdatajpa.springboot.repository;
  2. import com.springdatajpa.springboot.entity.Role;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. public interface RoleRepository extends JpaRepository<Role, Long> {
  5. }

6.测试多对多双向Map

让我们编写JUnit测试,使用Spring Data JPA测试多对多双向Map:

  1. package com.springdatajpa.springboot.repository;
  2. import com.springdatajpa.springboot.entity.Role;
  3. import com.springdatajpa.springboot.entity.User;
  4. import org.junit.jupiter.api.Test;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import java.util.List;
  8. @SpringBootTest
  9. public class ManyToManyBidirectionalTest {
  10. @Autowired
  11. private RoleRepository roleRepository;
  12. @Test
  13. void saveRole(){
  14. User user = new User();
  15. user.setFirstName("ramesh");
  16. user.setLastName("fadatare");
  17. user.setEmail("ramesh@gmail.com");
  18. user.setPassword("secrete");
  19. User admin = new User();
  20. admin.setFirstName("admin");
  21. admin.setLastName("admin");
  22. admin.setEmail("admin@gmail.com");
  23. admin.setPassword("admin");
  24. Role roleAdmin = new Role();
  25. roleAdmin.setName("ROLE_ADMIN");
  26. roleAdmin.getUsers().add(user);
  27. roleAdmin.getUsers().add(admin);
  28. user.getRoles().add(roleAdmin);
  29. admin.getRoles().add(roleAdmin);
  30. roleRepository.save(roleAdmin);
  31. }
  32. @Test
  33. void fetchRole(){
  34. List<Role> roles = roleRepository.findAll();
  35. roles.forEach((r) ->{
  36. System.out.println(r.getName());
  37. r.getUsers().forEach((u) ->{
  38. System.out.println(u.getFirstName());
  39. });
  40. });
  41. }
  42. }

保存角色还将保存关联的用户(Cascade.PERSIST):

  1. @Test
  2. void saveRole(){
  3. User user = new User();
  4. user.setFirstName("ramesh");
  5. user.setLastName("fadatare");
  6. user.setEmail("ramesh@gmail.com");
  7. user.setPassword("secrete");
  8. User admin = new User();
  9. admin.setFirstName("admin");
  10. admin.setLastName("admin");
  11. admin.setEmail("admin@gmail.com");
  12. admin.setPassword("admin");
  13. Role roleAdmin = new Role();
  14. roleAdmin.setName("ROLE_ADMIN");
  15. roleAdmin.getUsers().add(user);
  16. roleAdmin.getUsers().add(admin);
  17. user.getRoles().add(roleAdmin);
  18. admin.getRoles().add(roleAdmin);
  19. roleRepository.save(roleAdmin);
  20. }

提取角色还将提取其关联用户(提取类型EAGER):

  1. @Test
  2. void fetchRole(){
  3. List<Role> roles = roleRepository.findAll();
  4. roles.forEach((r) ->{
  5. System.out.println(r.getName());
  6. r.getUsers().forEach((u) ->{
  7. System.out.println(u.getFirstName());
  8. });
  9. });
  10. }

相关文章