JPA的关系及配置

1.单向一对多

映射配置

//一方
@Entity
public class Product {
  @Id
  @GeneratedValue
  private Long id;
  private String name;
  //多方
  @Entity
public class ProductDir {
  @Id
  @GeneratedValue
  private Long id;
  private String name;
  @OneToMany
  // 必须配置外键id,否则会多生成一张表,形成多对多的关系
  @JoinColumn(name = "dir_id")
  // 建议实例化,用的时候不需要在实例化,这里和单向多对一要求不同
  private Set<Product> products = new HashSet<Product>();  

保存代码

  public void persist() throws Exception {
  // 一方
  ProductDir dir = new ProductDir();
  dir.setName("类型1");
  // 多方
  Product product = new Product();
  product.setName("产品1");
  Product product2 = new Product();
  product2.setName("产品2");
  // 连接关系(只能由一方建立到多方的关系)
  dir.getProducts().add(product);
  dir.getProducts().add(product2);
  EntityManager entityManager = JPAUtils.getEntityManager();
  entityManager.getTransaction().begin();
  // 保存一方(产品)
  entityManager.persist(dir);
  // 保存多方(产品类型)
  entityManager.persist(product2);
  entityManager.persist(product);
  entityManager.getTransaction().commit();
  entityManager.close();
}

保存性能

不管怎么保存(改变persist代码位置),它都会至少执行5条SQL语句完成保存功能。
而完成同样的功能,我们使用单向多对一可以优化为3条。 因此,我们一般不使用单向一对多
原因就是现在外键是由一方来处理,一方处理必须发出额外的update语句

获取代码

 @Test
public void get() throws Exception {
  EntityManager entityManager = JPAUtils.getEntityManager();
  // 拿到一方(产品类别)的数据
  ProductDir dir = entityManager.find(ProductDir.class, 1L);
  // 打印产品类别
  System.out.println(dir);
  // 打印产品类别
  System.out.println(dir.getProducts());
  // 判断该产品类别中是否有产品
  if (dir.getProducts().size() == 0) {
    System.out.println("当前产品没有类型");
  } else {
    System.out.println("当前产品有类型");
  }
  entityManager.close();
}

注意事项

1.配置集合的时候必须配置接口
2.一般都是使用Set接口,只有组合关系使用List接口
3.使用List接口的时候可以配置@Order进行排序
4.实体类不能使用Final修饰(不能继承)

2.双向多对一/双向一对多

配置

配置:尽量让多方来维护的关系,一方放弃管理mappedBy

     @OneToMany(mappedBy = "dir")
    private List<Product> products = new ArrayList<>();
@Entity
public class ProductDir {
  @Id
  @GeneratedValue
  private Long id;
  private String name;
  // mappedBy = "dir"表示一方的关系参照多方Prodcut属性dir来管理
  @OneToMany( mappedBy = "dir")
  // 建议实例化,用的时候不需要在实例化,这里和单向多对一要求不同
  private Set<Product2> products = new HashSet<Product2>();
@Entity
public class Product {
  @Id
  @GeneratedValue
  private Long id;
  private String name;
  // 多Product对一ProductDir
  // 多个产品属于一个产品类型
  // 外键在那个表,这个表就是多
  @ManyToOne(fetch = FetchType.LAZY) // 实现延迟加载
  // JoinColum设置了外键的名字,不配置默认一方属性名_id
   @JoinColumn(name = "dir_id")
  // 这里进行了实例(这种写法是错误的,我们一定不能在这里进行实例化)
  private ProductDir dir;

保存

  // 一方
    ProductDir dir = new ProductDir();
    dir.setName("类型1");
    // 多方
    Product product = new Product();
    product.setName("产品1");
    Product product2 = new Product();
    product2.setName("产品2");
    // 只能由一方建立到多方的关系(设置外键)
    dir.getProducts().add(product);
    dir.getProducts().add(product2);
    EntityManager entityManager = JPAUtils.getEntityManager();
    entityManager.getTransaction().begin();
    entityManager.persist(dir);
    entityManager.persist(product);
    entityManager.persist(product2);
    entityManager.getTransaction().commit();
    entityManager.close();
    System.out.println("-------------------");

级联操作(掌握)

级联:就是我操作一方数据,就同时可以多方的数据也一并操作级联分为:

	 级联保存
	 :@OneToMany(cascade = CascadeType.PRESIST)
     级联删除(谨慎使用):
     @OneToMany(cascade = CascadeType.REMOVE)  

孤儿删除(掌握)

让一方解除关系 ,才能从1方删除多方

@OneToMany(cascade=CascadeType.REMOVE,mappedBy = "dir",orphanRemoval =true)

2.4 强级联 --后面项目里使用 组合关系(单据)

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

3.单向多对多

配置

User

@Entity
@Table(name="t_user")
public class User {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name="t_user_role",
    		joinColumns={@JoinColumn(name="user_id")},
            inverseJoinColumns ={@JoinColumn(name="role_id")} )
    private Set<Role> roles = new HashSet<>();
}

Role

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

单向对多对保存数据

 //3个用户 2个角色
        User user1 = new User();
        user1.setName("哈哈");
        User user2 = new User();
        user2.setName("xixi");
        User user3 = new User();
        user3.setName("啦啦");
        Role role1 = new Role();
        role1.setName("演员");
        Role role2 = new Role();
        role2.setName("导演");
        //设置关系
        user1.getRoles().add(role1);
        user2.getRoles().add(role1);
        user3.getRoles().add(role1);
        user1.getRoles().add(role2);
        user2.getRoles().add(role2);
        //保存数据
        EntityManager entityManager = JpaUtils.getEntityManager();
        entityManager.getTransaction().begin();
        entityManager.persist(user1);
        entityManager.persist(user2);
        entityManager.persist(user3);
        entityManager.persist(role1);
        entityManager.persist(role2);
        entityManager.getTransaction().commit();

4.双向多对多

配置

配置

role方

@ManyToMany(fetch = FetchType.LAZY,cascade = CascadeType.REMOVE)
    @JoinTable(name="t_user_role",
    	joinColumns={@JoinColumn(name="role_id")},
        inverseJoinColumns ={@JoinColumn(name="user_id")} )
    private Set<User> users = new HashSet<>();

user方

 @ManyToMany(fetch = FetchType.LAZY,cascade = CascadeType.REMOVE)
    @JoinTable(name="t_user_role",
    		joinColumns={@JoinColumn(name="user_id")},
            inverseJoinColumns ={@JoinColumn(name="role_id")} )
    private Set<Role> roles = new HashSet<>();

User映射配置

@ManyToMany(cascade = CascadeType.PERSIST)
public void persist2() throws Exception {
  // 保存2个用户,保存3个角色(5条)
  User user1 = new User("user1");
  User user2 = new User("user2");
  Role role1 = new Role("role1");
  Role role2 = new Role("role2");
  Role role3 = new Role("role3");
  // 保存中间表:建立用户到角色关系user1(role1,role2),user2(role1,role2,role3)(5条)
  user1.getRoles().add(role1);
  user1.getRoles().add(role2);
  user2.getRoles().add(role1);
  user2.getRoles().add(role2);
  user2.getRoles().add(role3);
  EntityManager entityManager = JPAUtils.getEntityManager();
  entityManager.getTransaction().begin();
  // 保存用户的同时,级联保存角色
  entityManager.persist(user1);
  entityManager.persist(user2);
  entityManager.getTransaction().commit();
  entityManager.close();
  System.out.println("------------------------");
}

一对一

一对一 可以看成 一对多 或者 多对一的特殊情况
重点配置:

   (1)建议使用单向 多 对一 不要使用单向一对多
   ​(2)如果要使用1对多,尽量使用双向配置,让1方放弃管理
   (3) 多对多 如果想相互获取数据 配置双向,如果单向操作 就配置单向
   (4)使用多对一来代替一对一,如果实在使用一对一 使用唯一外键的方式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值