一篇文章带你搞定 SpringDataJpa 中的多对多的多表设计

前面已经学习了:一篇文章带你搞定 SpringDataJpa 中的一对多的多表设计

本篇文章来学习SpringDataJpa 中的多对多的多表设计

一、前期配置

案例:用户和角色(多对多关系)

  • 用户
  • 角色

分析步骤:

  • 明确表关系:多对多关系
  • 确定表关系(描述 外键|中间表):中间间表
  • 编写实体类,再实体类中描述表关系(包含关系)
    • 用户:包含角色的集合
    • 角色:包含用户的集合
  • 配置映射关系

(1)实体类 User:

@Entity
@Table(name = "sys_user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="user_id")
    private Long userId;
    @Column(name="user_name")
    private String userName;
    @Column(name="age")
    private Integer age;

    /**
     * 配置用户到角色的多对多关系
     *      配置多对多的映射关系
     *          1.声明表关系的配置
     *              @ManyToMany(targetEntity = Role.class)  //多对多
     *                  targetEntity:代表对方的实体类字节码
     *          2.配置中间表(包含两个外键)
     *                @JoinTable
     *                  name : 中间表的名称
     *                  joinColumns:配置当前对象在中间表的外键
     *                      @JoinColumn的数组
     *                          name:外键名
     *                          referencedColumnName:参照的主表的主键名
     *                  inverseJoinColumns:配置对方对象在中间表的外键
     */
    @ManyToMany(targetEntity = Role.class,cascade = CascadeType.ALL)
    @JoinTable(name = "sys_user_role",
            //joinColumns,当前对象在中间表中的外键
            joinColumns = {@JoinColumn(name = "sys_user_id",referencedColumnName = "user_id")},
            //inverseJoinColumns,对方对象在中间表的外键
            inverseJoinColumns = {@JoinColumn(name = "sys_role_id",referencedColumnName = "role_id")}
    )
    private Set<Role> roles = new HashSet<>();
	//getter 和 setter 方法省略
}

(2)实体类 role:

@Entity
@Table(name = "sys_role")
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "role_id")
    private Long roleId;
    @Column(name = "role_name")
    private String roleName;

    //配置多对多
    @ManyToMany(mappedBy = "roles")  //配置多表关系
    private Set<User> users = new HashSet<>();
	//getter 和 setter 方法省略
}

(3)UserDao

public interface UserDao extends JpaRepository<User,Long>, JpaSpecificationExecutor<User> {}

(4)RoleDao

public interface RoleDao extends JpaRepository<Role,Long>, JpaSpecificationExecutor<Role> {}

(4)applicationContext:一篇文章带你快速入门 Spring Data JPA

二、多对多放弃维护权

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class ManyToManyTest {

    @Autowired
    private UserDao userDao;
    @Autowired
    private RoleDao roleDao;

    /**
     * 保存一个用户,保存一个角色
     *
     *  多对多放弃维护权:被动的一方放弃
     */
    @Test
    @Transactional
    @Rollback(false)
    public void  testAdd() {
        User user = new User();
        user.setUserName("小李");

        Role role = new Role();
        role.setRoleName("java程序员");

        //配置用户到角色关系,可以对中间表中的数据进行维护     1-1
        user.getRoles().add(role);

        //配置角色到用户的关系,可以对中间表的数据进行维护     1-1
        role.getUsers().add(user);

        userDao.save(user);
        roleDao.save(role);
    }
}

在这里插入图片描述

这里的主键并没有出现建立两次而出错,是因为 Role 表中放弃了对外键的维护权:
在这里插入图片描述

三、级联添加

上面的 User 表已经设置了级联操作:
在这里插入图片描述

    //测试级联添加(保存一个用户的同时保存用户的关联角色)
    @Test
    @Transactional
    @Rollback(false)
    public void  testCasCadeAdd() {
        User user = new User();
        user.setUserName("小李");

        Role role = new Role();
        role.setRoleName("java程序员");

        //配置用户到角色关系,可以对中间表中的数据进行维护     1-1
        user.getRoles().add(role);

        //配置角色到用户的关系,可以对中间表的数据进行维护     1-1
        role.getUsers().add(user);

        userDao.save(user);
    }

在这里插入图片描述

三、级联删除

同样此时需要设置 applicationContext 配置文件里,这里需要设置为 update,因为这里需要用到数据了,不能重新创建
在这里插入图片描述

    /**
     * 案例:删除id为1的用户,同时删除他的关联对象
     */
    @Test
    @Transactional
    @Rollback(false)
    public void  testCasCadeRemove() {
        //查询1号用户
        User user = userDao.findOne(1l);
        //删除1号用户
        userDao.delete(user);

    }

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/nanhuaibeian/article/details/107469257