java - JPA - JpaRepository 子记录具有父 ID 而不是实体记录,如果父记录已获取

标签 java spring-boot jpa spring-data-jpa spring-boot-2

这个问题在这里已经有了答案:





Hibernate bidirectional @ManyToOne, updating the not owning side not working

(3 个回答)


去年关闭。




我仍在掌握 JPA 概念,似乎无法在任何地方找到我的问题的答案!

认为

这两个类都用@GeneratedValue(strategy = GenerationType.IDENTITY) 进行了注解,都有getter 和setter。

Parent{
    ....
    @OneToMany(mappedBy = "parent")
    Collection<Child> children;
    ....
}

Child{
    ...
    @JoinColumn(name = "parent", referencedColumnName = "id", nullable = true)
    @ManyToOne(optional = false)
    Parent parent;
    ...
}

然后我实现了标准的 JpaRepository 并设置了我的 Controller

这是问题
当我查询所有子记录时,只有映射到特定父级的第一个子记录才会在其中包含父实体对象。其余的将有一个引用父实体的 id。

下面是一个例子:
从 POSTMAN 获取所有子项返回:
[
    {
        "id": 1,
        "name": "child1",
        "parent": {
            "id": 1,
            "firstName": "..."
            ...
            }
    },
    {
        "id": 2,
        "name": "child2",
        "parent": 1
    }
    {
        "id": 3,
        "name": "child3",
        "parent": {
            "id": 2,
            "firstName": "..."
            ...
            }
    },
    {
        "id": 4,
        "name": "child4",
        "parent": 2
    }
]

如您所见 child2只有"parent": 1child1首先映射到该父级!
同样child4只有"parent": 2child3首先映射到该父级!

任何人都可以解释这种行为吗?我试过 fetch = FetchType.EAGER在 parent 身上,但它没有帮助!
我希望所有 child 都有一个全面的父对象,以防止再次 DB 旅行。

提前致谢!

使用实际类(class)更新问题:

家长
package backend.application.payroll.models;

import com.fasterxml.jackson.annotation.*;
import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.*;

@Data
@Entity
@Table(name = "employees")
@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,
        property = "id")
public class Employee implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    @Column(name = "emp_code", nullable = false)
    private String empCode;
    @Column(name = "first_name", nullable = false)
    private String firstName;
    @Column(name = "middle_name", nullable = true)
    private String middleName;
    @Column(name = "last_name", nullable = false)
    private String lastName;
    @Column(name = "dob", nullable = false)
    @Temporal(TemporalType.DATE)
    private Date dob;
    @Column(name = "id_number", nullable = true)
    private String idNumber;
    @Column(name = "passport_number", nullable = true)
    private String passportNumber;
    @Column(name = "email_address", nullable = true)
    private String emailAddress;
    @OneToOne(cascade = CascadeType.DETACH)
    @JoinColumn(name = "pay_grade", referencedColumnName = "id", nullable = true)
    private Salary payGrade;
    @Column(name = "basic_pay", nullable = true)
    private BigDecimal basicPay;
    @OneToOne(cascade = CascadeType.DETACH)
    @JoinColumn(name = "department", referencedColumnName = "id", nullable = true)
    private Department department;
    @OneToOne(cascade = CascadeType.DETACH)
    @JoinColumn(name = "position", referencedColumnName = "id", nullable = true)
    private Position position;
    @Column(name = "tax_number", nullable = true)
    private String taxNumber;
    @Column(name = "hire_date", nullable = true)
    @Temporal(TemporalType.DATE)
    private Date hireDate;
    @Column(name = "address1", nullable = true)
    private String address1;
    @Column(name = "address2", nullable = true)
    private String address2;
    @Column(name = "postal_code", nullable = true)
    private String postalCode;
    //country
    @Column(name = "phone_number", nullable = true)
    private String phoneNumber;
    //banking details

    //HERE IT WORKS FINE SINCE IT'S ONETOONE - YOU CAN IGNORE
    @OneToOne(mappedBy = "employee")
    //@JsonManagedReference//used in conjunction with @JsonBackReference on the other end - works like @JsonIdentityInfo class annotation.
    private User user;

    //THIS IS WHAT CAUSING THE PROBLEM
    @OneToMany(mappedBy = "owner", fetch = FetchType.LAZY)
    //@JsonBackReference
    @JsonIgnore
    private Set<Costcentre> costcentres = new HashSet<>();

    public Employee() {

    }
}


child
package backend.application.payroll.models;

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import lombok.Data;

import javax.persistence.*;
import java.io.Serializable;


@Entity
@Table(name = "costcentres")
@Data
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Costcentre implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    @Column(name = "name", nullable = false)
    private String name;
    @Column(name = "description", nullable = true)
    private String description;
    @ManyToOne(cascade = CascadeType.DETACH, fetch = FetchType.EAGER)
    @JoinColumn(name = "owner", referencedColumnName = "id", nullable = true)
    //@JsonManagedReference
    private Employee owner; //CULPRIT

    public Costcentre() {

    }
    public Costcentre(long id, String name, String description) {
        super();
        this.id = id;
        this.name = name;
        this.description = description;
    }
}

最佳答案

添加 JsonIdentityInfo给 parent 和 child ,你可以添加 fetch = FetchType.EAGER在父级和 JsonIgnore 上忽略得到循环的 child 和 parent

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")

, 像这样:
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
Parent{
    ....
    @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
    @JsonIgnore
    Collection<Child> children;
    ....
}

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
Child{
    ...
    @JoinColumn(name = "parent", referencedColumnName = "id", nullable = true)
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    Parent parent;
    ...
}

关于java - JPA - JpaRepository 子记录具有父 ID 而不是实体记录,如果父记录已获取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61962472/

相关文章:

mysql - 使用 JPA 创建表

java - 运行 java -jar 命令时出错

java - 在选择的导航项上不显示带有选项卡布局的 fragment

java - 使用正则表达式在单个字符后删除零

java - 我需要从 java 类调用 Spring 服务,如何从 java 类设置 spring 应用程序的 Activity 配置文件

java - Spring 数据JPA : Check Exists Entity ID with @Query Annotation

java - 如何触发预定的 Spring Batch Job?

java - DI 将 String bean 作为 List<String> 的单个元素注入(inject),而不是正确的 List<String> bean

tomcat - SpringBoot JNDI 数据源抛出 java.lang.ClassNotFoundException : org. apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory

java - 复合 ID 及其在 JPA 中的生成