Spring引导 - 更新一个实体后,两个表中没有反映一对一关系

时间:2017-03-18 05:52:53

标签: java spring hibernate spring-boot spring-data

我有两个实体Employee and Review。我正在尝试创建OneToOne关系Employee< - >评论。

当我通过审核更新员工时,员工会在审核成为相应审核的地方得到更新, 但是评论没有得到评论者的认可。列添加了员工的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'

2 个答案:

答案 0 :(得分:1)

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

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

r.setReviewee(n);

请注意,下次检索审核时,它会正确显示Employee个对象。

注意:序列化时,我闻到了杰克逊的无限循环。

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

修改

防止杰克逊无限循环:

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;

    // ...
}

答案 1 :(得分:0)

它似乎是配置不匹配。请尝试下面的一个。

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

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

public class Review {
    @Id
    @GeneratedValue(generator="gen")    
    @GenericGenerator(name="gen", strategy="foreign", parameters={@Parameter(name="property",value="reviewee")})
    private Integer id;
    private String body;
    private char completed;

   @OneToOne    
   @PrimaryKeJoinCloumn    
   private Employee reviewee; }

我希望上面的配置按预期工作。

请确保您在“交易边界”下调用保存功能。否则,在关闭会话之前不要忘记调用flush()。