JPA继续探索

本文深入探讨了JPA中的关系映射,包括第一、二、三范式,以及单向一对多和级联操作。重点讨论了级联保存的目的、配置以及可能遇到的问题,如级联删除的危险性。同时,文章还涵盖了单向多对多的映射配置和级联保存,强调了在双向多对多关系中正确保存的策略以及级联删除的注意事项。
摘要由CSDN通过智能技术生成

范式

即不同的规范要求,在设计关系型数据库时,要遵从不同的规范要求,设计出合理的关系型数据库。

第一范式【1NF】:

具备原子性(最小单元,不可分割),主要是指表里的列,一个列一旦被创建后就不能再分开,一个列只能存放一个值。

第二范式【2NF】:

设计的表里面都应该要有一个唯一标识来区分表里每一行的数据,即主键。

第三范式【3NF】:

一个表里面尽量不要存放其他表的非关键性信息,即再表里存放外键。

单向一对多

1.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>();  

结论:

不论是先保存一方再保存多方,还是先保存多方再保存一方,使用一对多的时候,它都会至少执行5条SQL语句完成保存功能(如下)。我们一般不使用单向一对多(原因:性能太差)
//配置关系

		dir.getProducts().add(product1);
        dir.getProducts().add(product2);
        product1.setDir(dir);
        product2.setDir(dir);

Hibernate: insert into ProductDir (name) values (?)
Hibernate: insert into Product (name) values (?)
Hibernate: insert into Product (name) values (?)
Hibernate: update Product set dir_id=? where id=?
Hibernate: update Product set dir_id=? where id=?

获取代码

用延迟加载提高性能的

修改成FetchType.EAGER后,不管有没有找类型项目的商品,它都会马上发送SQL来去查询数据。

但是这种做法严重影响性能。–关联(join)查询影响性能

在配置映射关系的时候如果是@ManyToOne(fetch=FetchType.LAZY),@OneToMany(fetch=FetchType.LAZY) ,@ManyToMany(fetch=FetchType.LAZY) 都是默认使用延迟加载提高性能的。

只有Many在后面都是使用延迟加载获取数据。

集合映射

因为Hibernate在创建了集合对象后是使用了它的的集合类PersistentSet来接收数据的(而不是我们写的那个HashSet)。如果我们使用接口声明(如Set),那么它的集合类PersistentSet也是实现了这个接口。所以它可以把这个类赋给Set。 但是我们使用HashSet,它们关系是平级的,不能进行转换,所以就出现错误了。

结论:声明集合的时候必须使用接口

级联

操作一方,导致另一方受到影响

级联保存的目的:

我们直接保存商品类别(如:ProductDir,一方),就把它对应的商品(Product,多方)也一起保存起来

级联的配置:

映射配置:

@OneToMany(cascade = CascadeType.PERSIST, mappedBy = "dir")
private Set<Product> products = new HashSet<Product>();

@OneToMany(cascade = CascadeType.PERSIST, mappedBy = “dir”)

1.mappedBy = "dir"表示一方的关系参照多方Prodcut属性dir来管理

2.cascade = CascadeType.PERSIST

3.必须两边都建立关系

 // 只能由一方建立到多方的关系(设置外键)
  dir.getProducts().add(product);
  dir.getProducts().add(product2);
  // 指建立多方到一方的关系
  product.setDir(dir);
  product2.setDir(dir);

4.entityManager.persist(dir);只能保存一方

级联删除

可能会遇到的各种情况

  1. 级联删除:删除一方,然后级联删除多方(危险操作)

  2. 从一方去删除一个解除关系(外键的值为null)的多方:先获取一方,在删除一个多方

  3. 从一方去删除所有解除关系的多方:先获取一方,在删除所有多方

1\级联删除:删除一方,然后级联删除多方(危险操作)

示例:删除商品分类(ProductDir,一方),它下面的所有商品(Product,多方)都要删除

​ 如果我们直接删除的话,就发现报一个错(外键关系不能删除)

Cannot delete or update a parent row: a foreign key constraint fails (jpa.product, CONSTRAINT FK_dt353uy1bfcml55ixct2txdu2 FOREIGN KEY (dir_id) REFERENCES productdir (id))

所以必须配置一个级联 cascade = CascadeType.REMOVE

@Test
    //删除一方,然后级联删除多方(危险操作)
    public void testDel() throws Exception
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值