Skip to content
On this page

多对一

  • 在实体与实体的关系中,多对多和一对多是由于站的角度不同出现的不同问题。

  • 在数据库表中,当在多对一和一对多的表中建立关联关系时,都是在多的一方新增一列,让这一列的值对应“一方”的主键。该列可以增加外键约束,也可以不加

  • 而在面向对象语言中,在类和类的设计上多对一时在多的一方建立“一方”类型的对象,而在一对多是在“一方”建立“多方”类型的集合【如: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);
    }