如何解决带有嵌套连接的子句“where”无法使用 hql 查询
我有 3 个实体:
@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "event")
@FieldDefaults(level = AccessLevel.PRIVATE)
public class Event {
@Id
@GeneratedValue
@Column(name = "id")
UUID id;
@Column(name = "name",nullable = false,unique = true)
String name;
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
@JoinColumn(name = "event_id")
Set<Session> sessions;
}
@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "session")
@FieldDefaults(level = AccessLevel.PRIVATE)
public class Session {
@Id
@GeneratedValue
@Column(name = "id")
UUID id;
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
@JoinColumn(name = "session_id")
Set<SessionHistory> sessionHistory;
}
@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "session_history")
@FieldDefaults(level = AccessLevel.PRIVATE)
public class SessionHistory {
@Id
@GeneratedValue
@Column(name = "id")
UUID id;
@Column(name = "status",nullable = false)
@Enumerated(EnumType.STRING)
Status status;
}
事件存储库:
@Repository
public interface EventRepo extends JpaRepository<Event,UUID> {
Optional<Event> findByExternalId(Long externalId);
@Query("SELECT e FROM Event e " +
"JOIN e.sessions s " +
"JOIN s.sessionHistory sh WHERE sh.status = 'SALE'")
List<Event> findAllBy();
}
所以我想获取只有 SALE 状态的会话历史记录。测试:
SessionHistory sessionHistory1 = SessionHistory.builder()
.status(Status.SOON)
.build();
SessionHistory sessionHistory2 = SessionHistory.builder()
.status(Status.SALE)
.build();
Session session = Session.builder()
.sessionHistory(Sets.newSet(sessionHistory1,sessionHistory2))
.build();
Event event = Event.builder()
.name("SOMENAME")
.sessions(Collections.singleton(session))
eventRepo.save(event);
Optional<Event> event = eventRepo.findAllBy().stream().findAny();
assertEquals(1,eventByExternalId.get().getSessions()
.stream().findAny().get().getSessionHistory().size());
选择查询:
...
from
event event0_
inner join
session sessions1_
on event0_.id=sessions1_.event_id
inner join
session_history sessionhis2_
on sessions1_.id=sessionhis2_.session_id
where
sessionhis2_.status='SALE'
但测试失败并输出:
org.opentest4j.AssertionFailedError:
Expected :1
Actual :2
有什么问题吗?如果我们尝试在查询中对 Session 或 Event 使用“where”,它可以正常工作。也尝试过 join fetch。我没有找到 OneToMany 关联的解决方案。甚至有可能吗?我不想编写本机查询。如果您对此问题有一些复杂的方法,那就没问题(例如 EntityGraph)
解决方法
由于连接,您两次获得相同的实体。
添加不同的
@Query("SELECT distinct e FROM Event e " +
"JOIN e.sessions s " +
"JOIN s.sessionHistory sh WHERE sh.status = 'SALE'")
List<Event> findAllBy();
,
您的加入只是一个“随机加入”,不会影响会话历史关联的内容。如果你只想获取那个,我不推荐这个(点击链接进一步解释),你可以使用这个查询:
@Query("SELECT e FROM Event e " +
"JOIN FETCH e.sessions s " +
"JOIN FETCH s.sessionHistory sh WHERE sh.status = 'SALE'")
List<Event> findAllBy();
有关更详细的答案和基于 DTO 的替代解决方案,请查看此答案:Return ResultSet with intact joins in Hibernate / JPA
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。