JPA学习(五) 五种 映射关系

Myth丶恋晨 2022-05-14 11:45 178阅读 0赞

一、JPA_映射单向多对一的关联关系

1、创建实体类

  1. //订单
  2. @Table(name="JPA_ORDER")
  3. @Entity
  4. public class Order {
  5. private Integer id;
  6. private String orderName;
  7. private Customer customer;
  8. @Id
  9. @GeneratedValue
  10. public Integer getId() {
  11. return id;
  12. }
  13. public void setId(Integer id) {
  14. this.id = id;
  15. }
  16. @Column(name="ORDER_NAME")
  17. public String getOrderName() {
  18. return orderName;
  19. }
  20. public void setOrderName(String orderName) {
  21. this.orderName = orderName;
  22. }
  23. //映射多对一的关联关系
  24. //使用 @ManyToOne 来映射多对一的关联关系
  25. //使用 @JoinColumn 来映射外键 name:外键键名
  26. @JoinColumn(name="CUSTOMER_ID")
  27. @ManyToOne
  28. public Customer getCustomer() {
  29. return customer;
  30. }
  31. public void setCustomer(Customer customer) {
  32. this.customer = customer;
  33. }
  34. }

测试类:

  1. //数据表生成
  2. @Test
  3. public void testManyToOne(){
  4. }

保存数据 :

保存多对一时,建议先保存1的一端,然后保存 n 的一端,这样不会多出额外的 UPDATE 语句

  1. @Test
  2. public void testManyToOnePersist(){
  3. Customer customer = new Customer();
  4. customer.setAge(15);
  5. customer.setBirth(new Date());
  6. customer.setCreatTime(new Date());
  7. customer.setEmail("ee@flx.com");
  8. customer.setLastName("EE");
  9. Order order1 = new Order();
  10. order1.setOrderName("O-EE-1");
  11. Order order2 = new Order();
  12. order2.setOrderName("O-EE-2");
  13. //设置关联关系
  14. order1.setCustomer(customer);
  15. order2.setCustomer(customer);
  16. //执行保存操作
  17. entityManager.persist(customer);
  18. entityManager.persist(order1);
  19. entityManager.persist(order2);
  20. }

70

输出的SQL语句 : 是3 条insert 语句

70 1

如果把执行保存操作中调换顺序

  1. @Test
  2. public void testManyToOnePersist(){
  3. Customer customer = new Customer();
  4. customer.setAge(15);
  5. customer.setBirth(new Date());
  6. customer.setCreatTime(new Date());
  7. customer.setEmail("gg@flx.com");
  8. customer.setLastName("GG");
  9. Order order1 = new Order();
  10. order1.setOrderName("g-GG-1");
  11. Order order2 = new Order();
  12. order2.setOrderName("g-GG-2");
  13. //设置关联关系
  14. order1.setCustomer(customer);
  15. order2.setCustomer(customer);
  16. //执行保存操作
  17. entityManager.persist(order1);
  18. entityManager.persist(order2);
  19. entityManager.persist(customer);

那么执行结果: 【可以保存成功,SQL的变化】 三条insert 和两条update

70 2

70 3

70 4

70 5

这个时候外键是null 的 【下图 中 CUSTOMER_ID外键列的值 实际上为null 】

70 6

只有在保存外这个customer 之后,才知道外键列时谁,这个时候customer 才会有id; 【如下图】

70 7

然后jpa去维护关联关系,又额外有两个update。所以总结:

70 8

获取数据:

①、默认情况下,使用左外连接的方式来获取 n 的一端的对象和其关联的 1 的一端的对象

  1. @Test
  2. public void testManyToOneFind(){
  3. Order order = entityManager.find(Order.class, 1);
  4. System.out.println(order.getOrderName());
  5. System.out.println(order.getCustomer().getLastName());
  6. }

执行的结果: 【一条select 语句】

70 9

②、可使用 @ManyToOne 中的 fetch 属性来修改默认的关联属性的加载策略 【懒加载】

70 10

还是同样的测试 ,运行结果: 先生成Order 的信息 , 再打印Customer —查询customer 的语句 【两条SQL语句】

70 11

70 12

删除数据:

①、删除

  1. @Test
  2. public void testManyToOneRemove(){
  3. Order order = entityManager.find(Order.class, 1);
  4. entityManager.remove(order);
  5. }

运行结果: 一个select 一个 delete

70 13

70 14

②、不能直接删除1 的一端,因为有外键关联

  1. @Test
  2. public void testManyToOneRemove(){
  3. Customer customer = entityManager.find(Customer.class, 7);
  4. entityManager.remove(customer);
  5. }

70 15

修改数据:

  1. @Test
  2. public void testManyToOneUpdate(){
  3. Order order = entityManager.find(Order.class, 2);
  4. order.getCustomer().setLastName("FFF");
  5. }

70 16

二、JPA_映射单向一对多的关联关系

生成数据表:

  1. @Test
  2. public void testOneToMany(){
  3. }

保存数据:

单向 1-n 关联关系执行保存时,一定会多出UPDATE语句,因为n 的一端在插入时不会同时插入外键列

  1. @Test
  2. public void testOneToManyPersist(){
  3. Customer customer = new Customer();
  4. customer.setAge(18);
  5. customer.setBirth(new Date());
  6. customer.setCreatTime(new Date());
  7. customer.setEmail("zz@flx.com");
  8. customer.setLastName("ZZ");
  9. Order order1 = new Order();
  10. order1.setOrderName("O-ZZ-1");
  11. Order order2 = new Order();
  12. order2.setOrderName("O-ZZ-2");
  13. //建立关联关系
  14. customer.getOrders().add(order1);
  15. customer.getOrders().add(order2);
  16. //执行保存操作
  17. entityManager.persist(customer);
  18. entityManager.persist(order1);
  19. entityManager.persist(order2);
  20. }

结果是在控制台输出3条 insert 语句 和两条 update语句

70 17 70 18

70 19

查询数据:

①、默认对关联的多的一方使用懒加载的加载策略

  1. @Test
  2. public void testOneToManyFind(){
  3. Customer customer = entityManager.find(Customer.class, 9);
  4. System.out.println(customer.getLastName());
  5. System.out.println(customer.getOrders().size());
  6. }

70 20

②、可以使用 @OneToMany 的fetch 属性来修改默认的加载策略

70 21

测试:

  1. @Test
  2. public void testOneToManyFind(){
  3. Customer customer = entityManager.find(Customer.class, 9);
  4. System.out.println(customer.getLastName());
  5. System.out.println(customer.getOrders().size());
  6. }

运行结果变成了主外连接

70 22

删除数据:

①、默认情况下,若删除 1 的一端,则想把关联 n 的一端的外键置空,然后进行删除

  1. @Test
  2. public void testOneToManyRemove(){
  3. Customer customer = entityManager.find(Customer.class, 9);
  4. entityManager.remove(customer);
  5. }

运行结果 : 查询,然后把外键制空 , 最后删除

70 23 70 24 70 25

70 26 70 27

②、可以通过修改 @OneToMany 的 cascade 属性来修改默认的删除策略

70 28

  1. //默认情况下,若删除 1 的一端,则想把关联 n 的一端的外键置空,然后进行删除
  2. //可以通过修改 @OneToMany 的 cascade 属性来修改默认的删除策略
  3. @Test
  4. public void testOneToManyRemove(){
  5. Customer customer = entityManager.find(Customer.class, 8);
  6. entityManager.remove(customer);
  7. }

70 30" class="reference-link">70 29 70 30

更新数据:

  1. @Test
  2. public void testOneToManyUpdate(){
  3. Customer customer = entityManager.find(Customer.class, 11);
  4. customer.getOrders().iterator().next().setOrderName("O-xxx-11");
  5. }

70 31 70 32

三、JPA_映射双向一对多的关联关系 和双向多对一是一样的

1、实体类: Order 的实体类 加上 private Customer customer;,Customer 的实体类不变

  1. @Table(name="JPA_ORDERS") //订单
  2. @Entity
  3. public class Order {
  4. private Integer id;
  5. private String orderName;
  6. private Customer customer;
  7. @Id
  8. @GeneratedValue
  9. public Integer getId() {
  10. return id;
  11. }
  12. public void setId(Integer id) {
  13. this.id = id;
  14. }
  15. @Column(name="ORDER_NAME")
  16. public String getOrderName() {
  17. return orderName;
  18. }
  19. public void setOrderName(String orderName) {
  20. this.orderName = orderName;
  21. }
  22. @JoinColumn(name="CUSTOMER_ID")
  23. @ManyToOne(fetch=FetchType.LAZY)
  24. public Customer getCustomer() {
  25. return customer;
  26. }
  27. public void setCustomer(Customer customer) {
  28. this.customer = customer;
  29. }
  30. }

保存数据:

①、结论:若是双向1 - n 的关联关系,执行保存时:

若是先保存 n 的一端 , 再保存 1 的一端,默认情况下会多出 4 (n) 条 UPDATE 语句。

若是先保存 1 的一端,再保存 n 的一端,默认情况下会多出 2(n) 条 UPDATE 语句

  1. @Test
  2. public void testOneToManyDouble(){
  3. Customer customer = new Customer();
  4. customer.setAge(18);
  5. customer.setBirth(new Date());
  6. customer.setCreatTime(new Date());
  7. customer.setEmail("yy@flx.com");
  8. customer.setLastName("yy");
  9. Order order1 = new Order();
  10. order1.setOrderName("O-YY-1");
  11. Order order2 = new Order();
  12. order2.setOrderName("O-YY-2");
  13. //建立关联关系
  14. customer.getOrders().add(order1);
  15. customer.getOrders().add(order2);
  16. order1.setCustomer(customer);
  17. order2.setCustomer(customer);
  18. //执行保存操作
  19. entityManager.persist(order1);
  20. entityManager.persist(order2);
  21. entityManager.persist(customer);
  22. }

会有四条update 语句输出

70 33

②、控制台多出2条 UPDATE 语句

在进行双向 1-n 关联关系时,建议使用 n 的一方来维护关联关系,而1 的一方不维护关联关系,这样会有效的减少SQL语句。

  1. @Test
  2. public void testOneToManyDouble2(){
  3. Customer customer = new Customer();
  4. customer.setAge(18);
  5. customer.setBirth(new Date());
  6. customer.setCreatTime(new Date());
  7. customer.setEmail("ss@flx.com");
  8. customer.setLastName("ss");
  9. Order order1 = new Order();
  10. order1.setOrderName("O-SS-1");
  11. Order order2 = new Order();
  12. order2.setOrderName("O-SS-2");
  13. //建立关联关系
  14. customer.getOrders().add(order1);
  15. customer.getOrders().add(order2);
  16. order1.setCustomer(customer);
  17. order2.setCustomer(customer);
  18. //执行保存操作 =====》 更改顺序
  19. entityManager.persist(order1);
  20. entityManager.persist(order2);
  21. entityManager.persist(customer);
  22. }

结果大家自己去实现之后的控制台看吧 ,数据已经成功的保存在数据库里了。

③、注意:若在 1 的一端的 @OneToMany 中使用 mappedBy 属性,则 @OneToMany 端就不能再使用 @JoinColumn 属性了。

70 34

70 35

四、JPA_映射双向一对一的关联关系

五、JPA_映射双向多对多的关联关系

发表评论

表情:
评论列表 (有 0 条评论,178人围观)

还没有评论,来说两句吧...

相关阅读

    相关 UML中的关系

    UML中的关系(Relationships)主要包括5种:关联关系、聚合关系、依赖关系、泛化关系和实现关系。 关联(Association)关系 关联关系是一种