我们正在构建约会计划程序。我们有很多客人,每个客人都可以访问许多事件:实体“来宾”和“事件”。中间实体很多,称为“ EventGuestRelation”。它具有@EmbeddedId和两个Integer外键列,该列可以很好地运行,并且内置JPArepository方法的行为正常。
问题是当我查询EventGuestRelation的存储库时。 我无法让程序返回包含特定事件或特定来宾的EventGuestRelations。仅为零。为了简洁起见,我在这里显示有关事件的查询。
我尝试过
@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。 一些吉祥物只是拒绝变得晦涩难懂。
答案 0 :(得分:0)
我从未与@Embeddable
实体合作。也许,您可以在Spring-Data docs的本文中使用一些有用的东西,但是作为备份计划,我认为您始终可以使用本机SQL重写查询。
@Query(value = "SELECT e FROM event_guest_relation AS egr JOIN event AS e ON egr.event_id = e.id WHERE egr.event_id = :eventId", nativeQuery = true)
public List<EventEntity> getEventIdsForEvent(@Param(value = "eventId") Integer eventId);
和
@Query(value = "SELECT egr FROM event AS e JOIN event_guest_relation AS egr ON egr.event_id = e.id WHERE e.id = :eventId", nativeQuery = true)
public List<EventGuestRelation> findByEvent(@Param(value = "eventId") Integer eventId);
答案 1 :(得分:0)
联接列的名称必须与嵌入式主键中的列的相应名称相同。我错过了。因此,我的中间实体在数据库中有4列而不是2列。这导致查询返回null。 在我使名字相等之后,查询就起作用了。
已更正的中间实体具有嵌入式密钥:
@Column(name = "GUEST_ID")
protected Integer userGuestId;
在连接列中:
@ManyToOne
@JoinColumn(name = "GUEST_ID", insertable = false, updatable = false)
private UserEntity guest;