Day59_JPAday3关系

1.单向一对多(掌握)

  • 声明集合必须使用接口,建议将集合new出来
  • 必须设置外键(不然会生成中间表)
  • 默认懒加载(集合都是默认懒加载)
  • 性能差不用,建议使用双向一对多,多对一

Product类(多方)

@Entity
@Table(name = "product")
public class Product {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    
	//get,set,方法省略...
}

ProductDir类(一方)

@Entity
@Table(name = "productdir")
public class ProductDir {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    
    @OneToMany//一对多,默认懒加载
    @JoinColumn(name = "dir_id")//不设外键,会默认生成中间表
    //必须使用接口声明集合
    private List<Product> products = new ArrayList<>();
	
    //省略get,set方法..
}

图解
单向一对多

2.双向一对多,多对一

  • 单向一对多不行,才用双向一对多,多对一
  • 一方放弃关系维护(实际也没维护能力,外键在的那方才有维护能力)

Employee类(多方)

@Entity
@Table(name = "employee")
public class Employee {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    /*
    * 多个员工对应一个部门
    * */
    @ManyToOne
    @JoinColumn(name = "department_id")
    private Department department;

	//get和set方法省略...
}

Department类(一方)

@Entity
@Table(name = "department")
public class Department {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    /*
    * 一个部门对应多个员工
    * */
    @OneToMany(mappedBy = "department")//映射Employee中的department字段名
    //@JoinColumn(name = "department_id")//一方放弃维护(也没能力维护)
    private List<Employee> employees = new ArrayList<>();
	
	//get和set方法忽略...
}

3.级联

cascade(级联)

  • CascadeType.PERSIST(级联保存)
  • CascadeType.MERGE(级联修改)
  • CascadeType.REMOVE(级联删除)慎用,危险
  • CascadeType.ALL(包含级联增删改)
  • orphanRemoval = true(孤儿删除)

(1)级联删除(危险慎用)

练习1:删除一方,同时删除多方

//删除部门的时候,同时删除员工
@OneToMany(mappedBy = "department",cascade = CascadeType.REMOVE)
@Test
public void testDelete01(){
        EntityManager entityManager = JPAUtil.createEntityManager();
        entityManager.getTransaction().begin();
        //查询一方部门
        Department department = entityManager.find(Department.class, 1L);
        //级联删除1 删除部门同时,删除员工
        entityManager.remove(department);
        entityManager.getTransaction().commit();
        entityManager.close();
}

练习2:删除一个与一方解除了关系的多方(用到孤儿删除)

孤儿删除 orphanRemoval = true

//orphanRemoval = true孤儿删除,删除解除了关系的
@OneToMany(mappedBy = "department",cascade = CascadeType.REMOVE,orphanRemoval = true)
 @Test
 public void testDelete02(){
        EntityManager entityManager = JPAUtil.createEntityManager();
        entityManager.getTransaction().begin();
        //查询一方部门
        Department department = entityManager.find(Department.class, 1L);
        //级联删除2 解除第一个员工与部门的关系,孤儿删除员工1
        department.getEmployees().remove(0);
        entityManager.getTransaction().commit();
        entityManager.close();
 }

练习3:解除所有关系,删除所有解除关系的多方(先获取一方,删除所有多方)

@OneToMany(mappedBy = "department",cascade = CascadeType.REMOVE,orphanRemoval = true)
@Test
public void testDelete03(){
        EntityManager entityManager = JPAUtil.createEntityManager();
        entityManager.getTransaction().begin();
        //查询一方部门
        Department department = entityManager.find(Department.class, 1L);
        //级联删除2 解除该部门所有员工与部门的关系,孤儿删除所有解除关系的员工
        department.getEmployees().clear();
        entityManager.getTransaction().commit();
        entityManager.close();
}

最强级联

@OneToMany(mappedBy = "department",cascade = CascadeType.ALL,orphanRemoval = true)

级联注意事项

  • 级联能不用就不用,如果要用,就使用最强级联
  • 组合关系时(如:超市小票) 使用最强级联

图解

在这里插入图片描述

4.单向多对多

User类

@Entity
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    /*
    * name:关连(中间)表名
    * joinColumns = @JoinColumn(name = "user_id")当前类(表)对应外键的名称
    * inverseJoinColumns = @JoinColumn(name = "role_id")关连类(表)对应外键的名称
    * */
    @ManyToMany
    /*@JoinTable(name = "user_role",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id"))*/
    private List<Role> roles = new ArrayList<>();
}   

Role(角色类)

@Entity
@Table(name = "role")
public class Role {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
}

测试

@Test
public void testSave(){
     //2个用户,3个角色
     //准备两个用户 
     User u1 = new User();
     u1.setName("章无忌");
     User u2 = new User();
     u2.setName("樟三疯");
     //准备三个角色 
     Role r1 = new Role();
     r1.setName("少林");
     Role r2 = new Role();
     r2.setName("武当");
     Role r3 = new Role();
     r3.setName("明教");

     //建立关系 
     //章无忌既是武当又是明教
     u1.getRoles().add(r2);
     u1.getRoles().add(r3);
     //樟三疯既是少林看,武当,又是明教
     u2.getRoles().add(r1);
     u2.getRoles().add(r2);
     u2.getRoles().add(r3);
     EntityManager entityManager = JPAUtil.createEntityManager();
     entityManager.getTransaction().begin();

     //保存用户
     entityManager.persist(u1);
     entityManager.persist(u2);
     //保存角色
     entityManager.persist(r1);
     entityManager.persist(r2);
     entityManager.persist(r3);

     entityManager.getTransaction().commit();
     entityManager.close();
 }

5.双向多对多

User类

@Entity
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    /*
    * name:关连(中间)表名
    * joinColumns = @JoinColumn(name = "user_id")当前类(表)对应外键的名称
    * inverseJoinColumns = @JoinColumn(name = "role_id")关连类(表)对应外键的名称
    * */
    @ManyToMany
    @JoinTable(name = "user_role",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id"))
    private List<Role> roles = new ArrayList<>();
}

Role(角色类)

@Entity
@Table(name = "role")
public class Role {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    @ManyToMany
    @JoinTable(name = "user_role",
            joinColumns = @JoinColumn(name = "role_id"),
            inverseJoinColumns = @JoinColumn(name = "user_id"))
    private List<User> users = new ArrayList<>();
}

注意:双向多对多,必须保证中间表的名称,字段统一

  • name:关连(中间)表名
  • joinColumns = @JoinColumn(name = “user_id”)当前类(表)对应外键的名称
  • inverseJoinColumns = @JoinColumn(name = “role_id”)关连类(表)对应外键的名称
@JoinTable(name = "user_role",
           joinColumns = @JoinColumn(name = "role_id"),
           inverseJoinColumns = @JoinColumn(name = "user_id"))

6.多对多(级联)

练习1:级联添加 添加用户时,顺便添加角色

@ManyToMany(cascade = CascadeType.PERSIST)

练习2:删除user1(注意不是级联删除) JPA自动删除中间表user1对应内容和user1

@Test
public void testDelete(){
    EntityManager entityManager = JPAUtil.createEntityManager();
    entityManager.getTransaction().begin();
    //中间表时JPA自己控制,添加删除都是自动的
    User u1 = entityManager.find(User.class, 1L);
    //直接删除,JPA自动删除中间表对应内容
    entityManager.remove(u1);
    entityManager.getTransaction().commit();
    entityManager.close();
}

练习3:一边配置联级删除 User类配置联级删除 删除user1

User u1 = entityManager.find(User.class, 1L);
entityManager.remove(u1);

效果如下

武当和明教都被删了

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

练习4:两边都配置联级删除,和user1有关的所有的信息都被删了
该例子中,所有数据都被删了

User u1 = entityManager.find(User.class, 1L);
entityManager.remove(u1);

多对多
在这里插入图片描述

7.一对一

唯一外键一对一(掌握) 唯一外键扩展性强,常用
共享主键一对一(了解) 关系强烈,扩展性不强
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值