学习Spring有两周时间了 , 个人觉得服务端主要实现的是数据关系的维护和数据结构的制定 , 以及由业务需求产生的CRUD , 只要保证对前端提供的接口稳定高效响应 , 具体的前端实现完全不关心.

这个是接触后端的一个感受 , Spring boot使用了特定的方式来进行配置 ,大大简化了后端开发人员的开发工作量 ,比如JPA:用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来 ,此时数据之间的关系维护和数据结构的制定就显得尤为关键 , 下面记录数据表对应关系中的常见关系:一对多关系.

数据表关系

下面用实际场景简单理解数据表之间的关系

一对一:我有一个身份证号 ;
一对多:我有多张银行卡;
多对多:我是招行、交行、建行的客户,但是这些银行用户均过亿。

一对多双向关联

下面以订单order和订单项orderitem来展示

创建订单实体类,代码如下:

  1. package learn.jpa.entity;
  2.  
  3. import java.util.HashSet;
  4. import java.util.Set;
  5.  
  6. import javax.persistence.CascadeType;
  7. import javax.persistence.Column;
  8. import javax.persistence.Entity;
  9. import javax.persistence.Id;
  10. import javax.persistence.OneToMany;
  11.  
  12. /**
  13. * 订单
  14. */
  15. @Entity // 定义类为实体类
  16. public class Order {
  17.  
  18. private String orderid;
  19. private float amount = 0f;
  20. private Set<OrderItem> item = new HashSet<OrderItem>();
  21.  
  22. @Id // 实体标识符,因为是字符串类型,所有不能用 @GeneratedValue,只能人为的赋值
  23. @Column(length=20)
  24. public String getOrderid() {
  25. return orderid;
  26. }
  27. public void setOrderid(String orderid) {
  28. this.orderid = orderid;
  29. }
  30. @Column(nullable = false)
  31. public float getAmount() {
  32. return amount;
  33. }
  34. public void setAmount(float amount) {
  35. this.amount = amount;
  36. }
  37. @OneToMany(cascade={CascadeType.REFRESH,CascadeType.PERSIST,CascadeType.MERGE})
  38. public Set<OrderItem> getItem() {
  39. return item;
  40. }
  41. public void setItem(Set<OrderItem> item) {
  42. this.item = item;
  43. }
  44.  
  45. }
  46. /**
  47. * 1 - N
  48. * 多的一端为关系维护端,关系维护端负责外键记录的更新
  49. *
  50. */

创建订单项实体类,代码如下

  1. package learn.jpa.entity;
  2.  
  3. import javax.persistence.Column;
  4. import javax.persistence.Entity;
  5. import javax.persistence.GeneratedValue;
  6. import javax.persistence.Id;
  7.  
  8. /**
  9. * 订单项
  10. */
  11. @Entity // 定义类为实体类
  12. public class OrderItem {
  13.  
  14. private int id;
  15. private String productName;
  16. private float sellPrice = 0f;
  17. private Order order;
  18.  
  19. @Id // 实体标识符
  20. @GeneratedValue // 主键自动增长
  21. public int getId() {
  22. return id;
  23. }
  24. public void setId(int id) {
  25. this.id = id;
  26. }
  27.  
  28. @Column(length=40,nullable=false)
  29. public String getProductName() {
  30. return productName;
  31. }
  32. public void setProductName(String productName) {
  33. this.productName = productName;
  34. }
  35.  
  36. @Column(nullable=false)
  37. public float getSellPrice() {
  38. return sellPrice;
  39. }
  40. public void setSellPrice(float sellPrice) {
  41. this.sellPrice = sellPrice;
  42. }
  43. public Order getOrder() {
  44. return order;
  45. }
  46. public void setOrder(Order order) {
  47. this.order = order;
  48. }
  49. }

注解:

1、@OneToMany(fetch=FetchType,cascade=CascadeType)

@OneToMany描述一个一对多的关联,该属性应该为集体类型,在数据库中并没有实际字段.

fetch:表示该属性的读取策略,有EAGER和LAZY两种,分别表示主支抓取和延迟加载,默认为EAGER.

cascade:表示级联操作策略,对于OneToMany类型的关联非常重要,通常该实体更新或删除时,其关联的实体也应当被更新或删除

(1)、CascadeType.MERGE级联更新:若items属性修改了那么order对象保存时同时修改items里的对象。对应EntityManager的merge方法

(2)、CascadeType.PERSIST级联刷新:获取order对象里也同时也重新获取最新的items时的对象。对应EntityManager的refresh(object)方法有效。即会重新查询数据库里的最新数据

(3)、CascadeType.REFRESH级联保存:对order对象保存时也对items里的对象也会保存。对应EntityManager的presist方法

(4)、CascadeType.REMOVE级联删除:对order对象删除也对items里的对象也会删除。对应EntityManager的remove方法

CascadeType.PERSIST只有A类新增时,会级联B对象新增。若B对象在数据库存(跟新)在则抛异常(让B变为持久态)

CascadeType.MERGE指A类新增或者变化,会级联B对象(新增或者变化)

CascadeType.REMOVE只有A类删除时,会级联删除B类;

CascadeType.ALL包含所有;

综上:大多数情况用CascadeType.MERGE就能达到级联跟新又不报错,用CascadeType.ALL时要斟酌下CascadeType.REMOVE

optional:是否允许该字段为null,该属性应该根据数据库表的外键约束来确定,默认为true

一对多延迟加载与关系维护

订单实体类,代码:

  1. package learn.jpa.entity;
  2.  
  3. import java.util.HashSet;
  4. import java.util.Set;
  5.  
  6. import javax.persistence.CascadeType;
  7. import javax.persistence.Column;
  8. import javax.persistence.Entity;
  9. import javax.persistence.FetchType;
  10. import javax.persistence.Id;
  11. import javax.persistence.OneToMany;
  12. import javax.persistence.Table;
  13.  
  14. /**
  15. * 订单
  16. */
  17. @Entity // 定义类为实体类
  18. @Table(name="orders")
  19. public class Order {
  20.  
  21. private String orderid;
  22. private float amount = 0f;
  23. private Set<OrderItem> item = new HashSet<OrderItem>();
  24.  
  25. @Id // 实体标识符,因为是字符串类型,所有不能用 @GeneratedValue,只能人为的赋值
  26. @Column(length=20)
  27. public String getOrderid() {
  28. return orderid;
  29. }
  30. public void setOrderid(String orderid) {
  31. this.orderid = orderid;
  32. }
  33. @Column(nullable = false)
  34. public float getAmount() {
  35. return amount;
  36. }
  37. public void setAmount(float amount) {
  38. this.amount = amount;
  39. }
  40. /**
  41. * 如果是一对多或多对多 fetch 默认是延迟加载,反之是立即加载
  42. * mappedBy="order" 表示由实体 OrderItem 中的 order 属性维护
  43. * @return
  44. */
  45. @OneToMany(cascade={CascadeType.REFRESH,CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE},
  46. fetch=FetchType.LAZY,mappedBy="order")
  47. public Set<OrderItem> getItem() {
  48. return item;
  49. }
  50. public void setItem(Set<OrderItem> item) {
  51. this.item = item;
  52. }
  53.  
  54. public void addOrderItem(OrderItem orderItem){
  55. orderItem.setOrder(this);
  56. this.item.add(orderItem);
  57. }
  58.  
  59. }
  60. /**
  61. * 1 - N
  62. * 多的一端为关系维护端,关系维护端负责外键记录的更新
  63. *
  64. */

mappedBy只有在双向关联时,才会使用这个属性

mappedBy=”另一方的关系引用属性”

订单项实体类,代码:

  1. package learn.jpa.entity;
  2.  
  3. import javax.persistence.CascadeType;
  4. import javax.persistence.Column;
  5. import javax.persistence.Entity;
  6. import javax.persistence.FetchType;
  7. import javax.persistence.GeneratedValue;
  8. import javax.persistence.Id;
  9. import javax.persistence.JoinColumn;
  10. import javax.persistence.ManyToOne;
  11. import javax.persistence.Table;
  12.  
  13. /**
  14. * 订单项
  15. */
  16. @Entity // 定义类为实体类
  17. public class OrderItem {
  18.  
  19. private int id;
  20. private String productName;
  21. private float sellPrice = 0f;
  22. private Order order;
  23.  
  24. @Id // 实体标识符
  25. @GeneratedValue // 主键自动增长
  26. public int getId() {
  27. return id;
  28. }
  29. public void setId(int id) {
  30. this.id = id;
  31. }
  32.  
  33. @Column(length=40,nullable=false)
  34. public String getProductName() {
  35. return productName;
  36. }
  37. public void setProductName(String productName) {
  38. this.productName = productName;
  39. }
  40.  
  41. @Column(nullable=false)
  42. public float getSellPrice() {
  43. return sellPrice;
  44. }
  45. public void setSellPrice(float sellPrice) {
  46. this.sellPrice = sellPrice;
  47. }
  48. @ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},fetch=FetchType.EAGER,optional=false)
  49. @JoinColumn(name="order_id")
  50. public Order getOrder() {
  51. return order;
  52. }
  53. public void setOrder(Order order) {
  54. this.order = order;
  55. }
  56. }

joinColumns属性表示,在保存关系中的表中,所保存关联关系的外键的字段。并配合@JoinColumn标记使用。

小结

理解关联表中存储的关系对含义, 记下使用的套路基本上就没什么问题了 ,下篇文章将记录多对多双向关联与级联操作 .

JPA中的一对多双向关联与级联操作的更多相关文章

  1. JPA学习---第九节:JPA中的一对多双向关联与级联操作

    一.一对多双向关联与级联操作 1.创建项目,配置文件代码如下: <?xml version="1.0" encoding="UTF-8"?> < ...

  2. JPA学习---第十一节:JPA中的多对多双向关联实体定义与注解设置及操作

    1.定义实体类,代码如下: (1).学生实体类: package learn.jpa.entity; import java.util.HashSet; import java.util.Set; i ...

  3. Hibernate从入门到精通(九)一对多双向关联映射

    上次的博文Hibernate从入门到精通(八)一对多单向关联映射中,我们讲解了一下一对多单向映射的相关内容,这次我们讲解一下一对多双向映射的相关内容. 一对多双向关联映射 一对多双向关联映射,即在一的 ...

  4. Hibernate(九)一对多双向关联映射

    上次的博文Hibernate从入门到精通(八)一对多单向关联映射中,我们讲解了一下一对多单向映射的相关 内容,这次我们讲解一下一对多双向映射的相关内容. 一对多双向关联映射 一对多双向关联映 射,即在 ...

  5. Hibernate 一对多双向关联Demo

    以Classes[班级]和Student[学生]为例的Demo //Classes.java public class Classes implements Serializable { privat ...

  6. hibernate 一对多双向关联 详解

    一.解析: 1.  一对多双向关联也就是说,在加载班级时,能够知道这个班级所有的学生. 同时,在加载学生时,也能够知道这个学生所在的班级. 2.我们知道,一对多关联映射和多对一关联映射是一样的,都是在 ...

  7. Hibernate中用注解配置一对多双向关联和多对一单向关联

    Hibernate中用注解配置一对多双向关联和多对一单向关联 Hibernate提供了Hibernate Annotations扩展包,使用注解完成映射.在Hibernate3.3之前,需单独下载注解 ...

  8. SpringData_04_ JPA中的一对多

    1.JPA中的一对多 在一对多关系中,我们习惯把一的一方称之为主表,把多的一方称之为从表.在数据库中建立一对多的关系,需要使用数据库的外键约束. 什么是外键? 指的是从表中有一列,取值参照主表的主键, ...

  9. grails一对多双向关联

    前面分享了一些学习grails的心得,可是grails的知识还远不止这些,这次整理了一点有关grails一对多双向关联关系的知识.我认为这样的关联用的地方太多了,这次准备的样例是城市和区域的相关样例. ...

随机推荐

  1. centos7安装maven

    下载maven 下载地址:http://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache-maven-3. ...

  2. 实现多线程的另一种方式-Callable

    package com.mldn.thread; import java.util.concurrent.ExecutionException; import java.util.concurrent ...

  3. UEFI引导模式

    Author: JinDate: 20140827System: windows 刚帮楼下的公司解决了个问题. 原来的办公电脑,预装linux,他们重装成win7.新买的电脑预装成win8,安装出问题 ...

  4. [翻译] AFNetworking 2.0

    大名鼎鼎的开源网络库AFNetworking 2.0,目前只是翻译了Github上的链接文章,使用教程请点击 http://www.cnblogs.com/YouXianMing/p/3651462. ...

  5. Python3.6学习笔记(六)

    WSGI Python Web Server Gateway Interface 规范学习 由于Python的灵活性,提供了多种方式可以作为服务端语言,包括Python编写的服务器(Medusa).P ...

  6. Java中使用Jedis操作Redis之二

    import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.J ...

  7. PHP array与Json学习

    在 PHP 中,有三种数组类型: 索引数组 - 带有数字索引的数组,(可以理解C/C++/Java中的数组,按照索引位置直接访问) 关联数组 - 带有指定键的数组,(可以理解为map,按照键值对存储, ...

  8. linux C 多线程/线程池编程 同步实例

    在多线程.线程池编程中经常会遇到同步的问题. 1.创建线程 函数原型:int pthread_create(pthread_t *thread, const pthread_attr_t *attr, ...

  9. Proxy 代理模式 动态代理 cglib MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  10. IOS Key-Value Observing (KVO)

    kvo,与观察者模式类似,通过给指定的对象设置观察者,来检测对象的变化,当指定的对象的属性被修改后,用于作为观察者的对象会接收到通知.简单的说就是每次指定的被观察的对象的属性被修改后,kvo就会自动通 ...