获取ManyToMany映射表的ID [英] Get id's of a ManyToMany mapping table
问题描述
我正在使用Spring Boot和Hibernate编写一个API,其中我的持久实体对象也用作发送到客户端和从客户端发送的DTO。这是我使用的典型实体的简化版本:
@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>组id;
$ b $ @ @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设置< Student> students = new HashSet<>();
// getters and setters
}
尽可以请参阅 Student
和组之间的
@ManyToMany
关联>。
由于我将这些对象发送给客户端,因此我只选择发送关联的id,而不发送关联本身。我已经解决了这个问题,使用这个答案,并按预期工作。
问题是这样的。当hibernate尝试保存一个 Student
对象时,它会按照预期插入 groups
,但它也会尝试插入 groupIds
放入映射表 GROUP_STUDENT
中。这当然会失败,因为映射表组合标识的唯一约束。而且 insertable = false
,因为它是 @ElementCollection
。我不认为我可以使用 @Formula
,因为我需要一个 Set
而不是减少的值。
当然可以通过清空 所以我想要的基本上是一个只读<$ c $在 groupIds $
,它从 groups
c $ c>在保存或保留这样一个实体之前,但这是非常危险和容易忘记。
Student
类中的c> groupIds GROUP_STUDENT
映射表中加载数据。这可能吗?我非常感谢任何建议,并且很乐意在这个问题上进行细化,看看是否还不清楚。
我已经设法解决这通过使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)
私人长ID;
@Transient
private Set< Long>组id;
$ b $ @ @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
}
I'm writing an API using Spring Boot and Hibernate where my persisted entity objects are also used as DTOs sent to and from the client. This is a simplified version of a typical entity I use:
@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
}
and this is the associated class:
@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
}
As you can see, there is a @ManyToMany
association between Student
and Group
.
Since I send objects like these to the client, I choose to send only the id's of the associations and not the associations themselves. I've solved this using this answer and it works as expected.
The problem is this. When hibernate tries to persist a Student
object, it inserts the groups
as expected, but it also tries to insert the groupIds
into the mapping table GROUP_STUDENT
. This will of course fail because of the unique constraint of the mapping table composite id. And it isn't possible to mark the groupIds
as insertable = false
since it is an @ElementCollection
. And I don't think I can use @Formula
since I require a Set
and not a reduced value.
This can of course be solved by always emptying either the groups
of the groupIds
before saving or persisting such an entity, but this is extremely risky and easy to forget.
So what I want is basically a read only groupIds
in the Student
class that loads the data from the GROUP_STUDENT
mapping table. Is this possible? I'm grateful for any suggestions and glad to ellaborate on the question if it seems unclear.
I've managed to solve this by making the id-collection @Transient
and populating it using @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
}
这篇关于获取ManyToMany映射表的ID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!