2017-08-07 100 views
1

我正在使用Spring Boot和Hibernate編寫一個API,其中我的持久化實體對象也用作發送到客戶端和從客戶端發送的DTO。這是我用一個典型的實體的簡化版本:獲取一個ManyToMany映射表的ID

@Entity 
@Table(name = "STUDENT") 
public class Student { 
    @Id 
    @GeneratedValue 
    @Column(name = "ID") 
    private Long id; 

    @ElementCollection 
    @CollectionTable(name = "GROUP_STUDENT", 
        joinColumns = @JoinColumn(name = "GROUP_ID")) 
    @Column(name="STUDENT_ID") 
    private Set<Long> groupIds; 

    @JsonIgnore 
    @ManyToMany(fetch = FetchType.LAZY) 
    @JoinTable(name="GROUP_STUDENT", 
       joinColumns = @JoinColumn(name="GROUP_ID"), 
       inverseJoinColumns = @JoinColumn(name="STUDENT_ID") 
    ) 
    private Set<Group> groups = new HashSet<>(); 

    // getters and setters 
} 

,這是關聯的類別:

@Entity 
@Table(name = "GROUP") 
public class Group { 
    @Id 
    @GeneratedValue 
    @Column(name = "ID") 
    private Long id; 

    @JsonIgnore 
    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "groups") 
    private Set<Student> students = new HashSet<>(); 

    // getters and setters 
} 

正如你所看到的,有StudentGroup之間的@ManyToMany關聯。

因爲我發送這樣的對象給客戶端,所以我選擇只發送關聯的id而不發送關聯本身。我已經使用this answer解決了這個問題,它按預期工作。

問題是這樣的。當hibernate嘗試保留Student對象時,它會按預期插入groups,但它也會嘗試將groupIds插入到映射表GROUP_STUDENT中。這當然會失敗,因爲映射表組合標識的唯一約束。並且不可能將groupIds標記爲insertable = false,因爲它是@ElementCollection。而且我不認爲我可以使用@Formula,因爲我需要Set而不是降價。

這當然可以通過在保存或堅持這樣一個實體之前始終清空groupIdsgroups來解決,但這是非常危險且容易忘記的。

所以我想要的是Student類中的只讀groupIds,它加載了GROUP_STUDENT映射表中的數據。這可能嗎?我很感激任何建議,並且很高興在這個問題上精心研究這個問題是否看起來不清楚。

回答

1

我已經設法通過將ID收集@Transient和填充它使用@PostLoad來解決這個問題:

@Entity 
@Table(name = "STUDENT") 
public class Student { 
    @PostLoad 
    private void postLoad() { 
     groupIds = groups.stream().map(Group::getId).collect(Collectors.toSet()); 
    } 

    @Id 
    @GeneratedValue 
    @Column(name = "ID") 
    private Long id; 

    @Transient 
    private Set<Long> groupIds; 

    @JsonIgnore 
    @ManyToMany(fetch = FetchType.LAZY) 
    @JoinTable(name="GROUP_STUDENT", 
       joinColumns = @JoinColumn(name="GROUP_ID"), 
       inverseJoinColumns = @JoinColumn(name="STUDENT_ID") 
    ) 
    private Set<Group> groups = new HashSet<>(); 

    // getters and setters 
}