Appearance
多对一
在实体与实体的关系中,多对多和一对多是由于站的角度不同出现的不同问题。
在数据库表中,当在多对一和一对多的表中建立关联关系时,都是在多的一方新增一列,让这一列的值对应“一方”的主键。该列可以增加外键约束,也可以不加
而在面向对象语言中,在类和类的设计上多对一时在多的一方建立“一方”类型的对象,而在一对多是在“一方”建立“多方”类型的集合【如:Employee和Dept类】
如果双方都有对方的属性,则被成为双向多对一或者一对多关联
而要让Spring Data Jpa知道类与类之间的关系,首先还需要在类与类的关系上通过Spring Data Jpa提供的注解(ManyToOne、OneToMany、ManyToMany)进行关联关系的配置,然后Spring Data Jpa内部机制才会将关联关系维护起来
增加Dept部门内类
java
package com.huangjiliang.jpa.entity;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.persistence.*;
@Entity
@Table(name = "dept")
@Data
@Accessors(chain = true)
public class Dept {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column
private String deptName;
@Column
private String deptCode;
// @OneToMany
// private List<Employee> employees;
}
employee类增加关联部门信息
java
package com.huangjiliang.jpa.entity;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.persistence.*;
@Entity
@Table(name = "employee")
@Data
@Accessors(chain = true)
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "")
private Integer id;
@Column
private Integer userNumber;
@Column
private String name;
@Column
private String gender;
// @Transient
@Column
private Integer age;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "dept_id", foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))
private Dept dept;
}
- 启动项目时,会创建dept表,以及在employee增加dept_id字段关联到dept表的id中
@JoinColumn
- name:指定employee表中关联dept表的字段名称
- foreignKey:外键约束配置
@ManyToOne
fetch:决定关联数据是进行及时加载还是懒加载,默认你是Fetch.EAGER,即及时加载
- 懒加载是根据实际情况选择是否查询关联关系中的数据,如果fetch属性设置为FetchType.LAZY,则实现懒加载的效果。懒加载时,如下代码就不会关联查询部门信息,因为代码中没有使用部门信息
java@Test public void findAll() { List<Employee> all = employeeRepository.findAll(); for (Employee employee : all) { logger.info(employee.getName()); // logger.info(employee.getDept().getDeptName()); } }
- 但是多对一的查询并不会太影响数据库的性能,故按照@ManyToOne注解中的fetch属性的默认这是即使加载即可
cascade:关联关系进行增删改时,级联操作姑阿努西处理
- CascadeType.PERSIST:级联保存
- CascadeType.MERGE:级联更新
- CascadeType.REMOVE:级联删除
- CascadeType.REFRESH:级联刷新
- CascadeType.ALL:以上四种都是
在实际开发中,由于一般不会对实体进行级联增删改操作,因此可以不必对cascade属性设置。它的默认值时一个空数组,即不包含以上任何关联关系
级联保存测试
java
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST) // 级联保存测试
// @ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "dept_id", foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))
private Dept dept;
java
/**
* 级联保存测试
*/
@Test
public void insertCascade() {
Dept dept = new Dept();
dept.setDeptCode("1001").setDeptName("志愿军");
Employee employee = new Employee();
employee.setUserNumber(200).setAge(18).setName("邱少云").setGender("男").setDept(dept);
employeeRepository.save(employee);
}