【发布时间】:2019-08-09 19:55:44
【问题描述】:
我们正在构建一个约会计划程序。我们有很多客人,每个客人都可以访问许多事件:实体“Guest”和“Event”。这是一个多对多的中间实体,称为“EventGuestRelation”。它具有带有两个整数外键列的@EmbeddedId,可以正常保存,并且内置的 JPArepository 方法运行正常。
问题是当我查询 EventGuestRelation 的存储库时。 我无法让程序返回包含特定事件或特定访客的 EventGuestRelations。 只是零。为简洁起见,我在此处显示有关 Event 的查询。
我试过了
@Query("SELECT r.event FROM EventGuestRelation r WHERE r.event= :event")
public List<EventEntity> getEventIdsForEvent(@Param(value = "event") EventEntity event);
和
public List<EventGuestRelation> findByEvent(EventEntity event);
两者都产生 SQL:
Hibernate:
select
evententit1_.id as id1_3_,
...
from
user_event_guest eventguest0_
inner join
eventlist evententit1_
on eventguest0_.event_sub=evententit1_.id
where
eventguest0_.event_sub=?
正确的实体:
@Entity
@Table
public class EventEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
...
@OneToMany(mappedBy = "event" , cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
@JsonBackReference
private Set<EventGuestRelation> subscriptions = new HashSet<>();
...
中间实体:
@Entity
@Table
public class EventGuestRelation {
@Embeddable
public static class EventGuestId implements Serializable {
@Column(name = "EVENT_ID")
protected Integer eventId;
...
}
@EmbeddedId
protected EventGuestId id = new EventGuestId();
@ManyToOne
@JoinColumn(name = "event_sub", insertable = false, updatable = false)
private EventEntity event;
...
省略了左侧实体(来宾)。
存储库:
public interface EventGuestRepository extends JpaRepository<EventGuestRelation, EventGuestId> {
及部分测试方法:
private final UserEntity ALYSSA = new UserEntity();
private final EventEntity GUESTING = new EventEntity();
private final EventGuestRelation AGUESTING = new EventGuestRelation();
userRepo.save(ALYSSA); // cascades to intemediate entity, checked;
AGUESTING.subscribe(ALYSSA, GUESTING); //bidirectional relation setter
List<EventEntity> eventsII = eventGuestRepo.getEventIdsForEvent(GUESTING);
assertEquals(eventsII.size(), 1); // fails
我可以通过这种次优方式解决问题:
Set<EventGuestRelation> subscriptions = ALYSSA.getSubscriptions();
Set<EventEntity> events = subscriptions.stream().map(s -> s.getEvent()).collect(Collectors.toSet())
但显然这不如直接查询数据库那么优雅。
任何帮助将不胜感激。 附言和 SICP 的 Alyssa 一样。 一些吉祥物只是拒绝默默无闻。
【问题讨论】:
-
您的数据库中有
event_guest_relation表吗? -
是的,当然。我的行动计划是用模拟数据填充数据库并手动编写所需的查询;然后检查 JPA 生成的查询是否不同。
-
我通过从中间实体的 OneToMany 映射中删除 insertable 和 updatable 使查询
@Query("SELECT r.userGuest FROM EventGuestRelation r WHERE r.event = :event") public List<UserEntity> getGuestsForEvent (@Param(value = "event") EventEntity event);起作用。现在我要介绍什么样的问题?
标签: spring-data-jpa many-to-many jpql