java - Spring boot - 更新一个实体后,一对一关系未反射(reflect)在两个表上

标签 java spring hibernate spring-boot spring-data

我有两个实体“员工”和“审核”。我正在尝试创建一对一关系“员工 <-> 审核”。

当我用评论更新员工时,员工会更新,评论将成为相应的评论, 但评论没有添加带有员工 ID 的“评论者”列,这正是我所期望的。

我做错了什么?

这些是我的实体:

public class Employee {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;
    private String name;
    private String email;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "reviewee")
    private Review review;
}

public class Review {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;
    private String body;
    private char completed;


   @OneToOne(mappedBy = "review")
   private Employee reviewee;
}

这是我的employeeController更新函数:

@GetMapping(path="/update") 
    public @ResponseBody Employee updateEmployee (@RequestParam Integer id,
             @RequestParam(value = "name", required=false) String name,
             @RequestParam(value = "email", required=false) String email,
             @RequestParam() Integer reviewId) {

        Employee n = EmployeeRepository.findOne(id);

        if(name == null) {
            name = n.getName();
        }

        if(email == null) {
            email = n.getEmail();
        }

        n.setName(name);
        n.setEmail(email);

        Review r =  ReviewRepository.findOne(reviewId);

        n.setReview(r);
        EmployeeRepository.save(n);
        return n;
    }

请求:

curl 'localhost:8080/employees/update?id=2&reviewId=1'

最佳答案

由于关系的所有者(带有 @JoinColumn 的所有者)是 Employee,因此您必须通过保存 Employee 来创建/更新/删除关联 对象。

这就是您到目前为止正在做的事情。但 Hibernate 只会在您保存时更新所有者。您还应该在返回实体之前执行此操作:

r.setReviewee(n);

请注意,下次您检索评论时,它将正确地具有 Employee 对象。

注意:序列化时我闻到了 Jackson 无限循环的味道。

Employee.review -> Review -> Review.reviewee -> Employee -> Employee.review...

编辑

为了防止 jackson 无限循环:

1.忽略序列化。

Employee.java

public class Employee {

    // ...

    // Do not serialize this field
    @JsonIgnore

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "reviewee")
    private Review review;

    // ...
}

2.序列化为ID。

Employee.java

public class Employee {

    // ...

    // Serialize as a single value with the field "id"
    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")

    // Serialize as told by @JsonIdentityInfo immediately (if false -> on second and further occurrences)
    @JsonIdentityReference(alwaysAsId = true)

    // Rename to "review_id" (would be "review" otherwise)
    @JsonProperty(value = "review_id")

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "reviewee")
    private Review review;

    // ...
}

3.序列化为 ID 的替代方案:对外键的只读引用。

Employee.java

public class Employee {

    // ...

    // Do not serialize this field
    @JsonIgnore

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "reviewee")
    private Review review;

    // Read-only access to the foreign key
    @Column(name = "Review_id", insertable = false, updatable = false)
    private Integer reviewId;

    // ...
}

关于java - Spring boot - 更新一个实体后,一对一关系未反射(reflect)在两个表上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42871018/

相关文章:

java - 是否可以在运行时检索 lambda 表达式

spring - 使用 JTA 批量插入(EntityManager 不能使用 getTransaction)

java - 使用 native 查询的 JPA 查询返回 null 而不是实体列表

java - 将带有 case 子句的 Sql 转换为 Hql

java - 如何在 jsf 1.2 中使用 DynamicJasper

hibernate - 我们可以限制从 SessionFactory 获取的 session 数量吗?

java - 无法使用 Intent.FLAG_ACTIVITY_NEW_TASK

java - 是否有标准化的站点地图格式?

java - 需要帮助编写一个程序,找到最高和第二高的数字是一个系列

java - JBoss 7 覆盖 JNDI 数据源