SpringDataJPA实体类关系映射配置方式
作者:墙角斑驳
SpringDataJPA
//FetchType.LAZY:懒加载,加载一个实体时,定义懒加载的属性不会马上从数据库中加载 //FetchType.EAGER:急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载 //cascade = CascadeType.ALL 表示所有情况下均进行关联操作,即save-update和delete @JsonBackReference //解决循环引用问题 @JsonIgnoreProperties(value = "order") //解决循环引用问题,order内容大,不加载 //双向映射存在转json无限递归问题 需要注解来处理 推荐使用第二个注解 value值为对方表作映射的变量值
1.单向一对一映射
一方
//教师 @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String name; private long salary; @OneToOne @JoinColumn(name="PSPACE_ID") private ParkingSpace parkingSpace;
一方
//停车场 @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private int lot; private String location;
总结
添加时候需要先添加@OneToOne的那方,删除也是。
2.双向一对一映射
一方
//人员 @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private long id; private String name; @OneToOne @JoinColumn(name="DEPT_ID") @JsonIgnoreProperties(value = "person") private Department department;
一方
//部门 @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private long id; private String name; @OneToOne(mappedBy="department") @JsonIgnoreProperties(value = "department") private Person person;
总结
@JsonBackReference //解决循环引用问题 @JsonIgnoreProperties(value = "order") //解决循环引用问题,order内容大,不加载 //双向映射存在转json无限递归问题 需要注解来处理 推荐使用第二个注解 value值为对方表作映射的变量值
3.单向一对多映射
一方
@Id @GeneratedValue private Long id; @Column(length = 32) private String name; @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)//级联保存、更新、删除、刷新;延迟加载 @JoinColumn(name = "author_id")//在book表增加一个外键列来实现一对多的单向关联 private Set<Book> books = new HashSet<Book>();
多方
//单向一对多的情况下 多方不需要加任何关联标识 @Id @GeneratedValue private Long id; @Column(length=32) private String name;
总结
因为是单向的关联,多方不需要加任何的关联标识 只需要在一方添加即可
4.双向一对多映射
一方
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; //主键 private String name; //姓名 //描述客户可以有多个订单 @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL) @JsonBackReference private Set<Order> order = new HashSet<Order>();
多方
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private Double money; private String receiverInfo; //收货地址 // 订单与客户关联 @ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "c_id") //指定外键列 @JsonIgnoreProperties(value = "order") //解决循环引用问题,order内容大,不加载 private Customer customer; //描述订单属于某一个客户
总结
@JsonBackReference //解决循环引用问题 @JsonIgnoreProperties(value = "order") //解决循环引用问题,order内容大,不加载 //双向映射存在转json无限递归问题 需要注解来处理 推荐使用第二个注解 value值为对方表作映射的变量值
5.单向多对一映射
多方
@GeneratedValue @Id private Integer id; @Column(name="ORDER_NAME") private String orderName; //映射单向 n-1的关联关系 //使用@ManyToOne来映射多对一的关联关系 //使用@JoinColumn 来映射外键 //可使用 @ManyToOne 的fetch 属性来修改默认的关联属性的加载策略 @JoinColumn(name="CUSTOMER_ID") //此外键为一方的主键 @ManyToOne(fetch=FetchType.EAGER) private Customer customer;
一方
//单向多对一的情况下,一方不需要加任何关联标识 @GeneratedValue(strategy=GenerationType.AUTO) @Id private Integer id; private String lastName; private String email; private int age; private Date createdTime; private Date birth;
总结
保存多对一时,建议先保存1的一端,后保存n的一端,这样不会多出额外的update语句。
6.双向多对一映射
多方
@GeneratedValue @Id private Integer id; @Column(name="ORDER_NAME") private String orderName; //映射单向 n-1的关联关系 //使用@ManyToOne来映射多对一的关联关系 //使用@JoinColumn 来映射外键 //可使用 @ManyToOne 的fetch 属性来修改默认的关联属性的加载策略 @JoinColumn(name="CUSTOMER_ID") @ManyToOne(fetch=FetchType.EAGER) @JsonIgnoreProperties(value = {"customer","orders"}) private Customer customer;
一方
@GeneratedValue(strategy=GenerationType.AUTO) @Id private Integer id; @Column(name="LAST_NAME",length=50,nullable=false) private String lastName; private String email; private int age; //定义日期格式 @Temporal(TemporalType.TIMESTAMP) private Date createdTime; @Temporal(TemporalType.DATE) private Date birth; //映射单向1-n的关联关系 //使用@OneToMany 映射单向1-n的关联关系 //使用@JoinColumn 来映射外键的名称 //可以使用@OneToMany 的 fetch 属性来修改加载策略 //可以使用@OneToMany 的 cascade 属性来修改默认的删除策略 // @JoinColumn(name="CUSTOMER_ID") //一的一端放弃维持关联关系 @OneToMany(fetch=FetchType.EAGER,cascade={CascadeType.REMOVE},mappedBy="customer") @JsonIgnoreProperties(value = "orders") private Set<Order> orders = new HashSet<>();
总结
1.必须使用@JsonIgnoreProperties注解来拦截转json时无限递归的问题
2.若是双向 1-n 的关联关系, 执行保存时:
(1)若先保存 n 的一端, 再保存 1 的一端, 默认情况下, 会多出2n 条 UPDATE 语句;
(2)若先保存 1 的一端, 则会多出 n 条 UPDATE 语句。
(3)故在进行双向 1-n 关联关系时, 建议使用 n 的一方来维护关联关系, 而 1 的一方不维护关联系, 这样会有效的减少 SQL 语句(即,N的一端对应的表中使用外键关联1的一端,外键对应1的一端的表主键)
注意:若在 1 的一端的 @OneToMany 中使用 mappedBy 属性, 则 @OneToMany 端就不能再使用 @JoinColumn 属性了。
7.单向多对多映射
多方
@Id @GeneratedValue private Long id; private String name; // 表示多对多 @ManyToMany(cascade = CascadeType.ALL) // 中间表的表名 @JoinTable(name = "t_user_role", joinColumns = {@JoinColumn(name = "user_id")}, //反转 user这个表的 反面则是 role inverseJoinColumns = {@JoinColumn(name = "role_id")}) private Set<Role> roles = new HashSet<>();
多方
@Id @GeneratedValue private Long id; private String name;
总结
使用 @JoinTable
来映射中间表
1. name
指向中间表的名字
2. joinColumns
映射当前类所在的表在中间表中的外键
2.1 name
指定外键列的列名
2.2 referencedColumnName
指定外键列关联当前表的哪一列
3. inverseJoinColumns
映射关联的类所在中间表的外键
8.双向多对多映射
多方
@Id @GeneratedValue private Long id; private String name; // 表示多对多 @ManyToMany(fetch = FetchType.LAZY,cascade = CascadeType.REMOVE) @JoinTable(name="t_user_role",joinColumns={@JoinColumn(name="user_id")}, inverseJoinColumns ={@JoinColumn(name="role_id")} ) @JsonIgnoreProperties(value = "users") private Set<Role> roles = new HashSet<>()
多方
@Id @GeneratedValue private Long id; private String name; @ManyToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL) @JoinTable(name="t_user_role",joinColumns={@JoinColumn(name="role_id")}, inverseJoinColumns ={@JoinColumn(name="user_id")} ) @JsonIgnoreProperties(value = "roles") private Set<User> users = new HashSet<>();
总结
使用 @JoinTable
来映射中间表
1. name
指向中间表的名字
2. joinColumns
映射当前类所在的表在中间表中的外键
2.1 name
指定外键列的列名
2.2 referencedColumnName
指定外键列关联当前表的哪一列
3. inverseJoinColumns
映射关联的类所在中间表的外键
@JsonBackReference //解决循环引用问题 @JsonIgnoreProperties(value = "order") //解决循环引用问题,order内容大,不加载
双向映射存在转json无限递归问题 需要注解来处理 推荐使用第二个注解 value值为对方表作映射的变量值
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。