Hibernate 复杂连接
Hibernate Complex Join
所以我们有 2 个对象,每个映射到一个数据库 table。
public class Dispute {
private Long disputeSeqNo;
private List<StatusInfo> statusInfos;
}
public class StatusInfo {
private Long statusSeqNo;
private Date createdDt;
private String statusCd;
private Dispute dispute;
}
一个争议可以有 0 个或多个与之关联的 StatusInfo。
目前,hibernate 正在为每个 Dispute 返回所有 StatusInfo 对象。虽然在某些情况下这是需要的。但是我有一个用例:
- 我只需要显示每个争议的最新 StatusInfo。
- 此外,在同一个显示器上,我需要能够按最近的 StatusInfo.statusCd 值排序。这种排序需要在数据库中进行,因为我的显示是分页的(使用休眠分页工具)。 (在检索后对数据进行排序确实不是一个选项,因为会有很多行数据。)
我知道使用简单的 SQL 我可以做到这一点,努力将其转换为 HQL。
关于如何使用 HQL 解决这个问题有什么想法吗?我还回来的地方:
List<Dispute>
感谢您的反馈。
谢谢!
您需要做的第一件事是在下面定义一个 Hibernate 过滤器。您可以简单地在 Dispute
class.
的顶部添加此注释
@FilterDef( name = "dispute-with-latest-statusinfo" )
接下来您需要在您的 StatusInfo
集合上应用这个命名过滤器,如下所示:
@OneToMany( mappedBy = "dispute" )
@Filter(
name = "dispute-with-latest-statusinfo",
condition = "statusinfo_id = (select max(si.statusinfo_id) from
StatusInfo si WHERE si.dispute_dispute_id = dispute_dispute_id")
private List<StatusInfo> statusInfos;
为了满足您的第一个要求,您可以获得 Dispute
个实例及其最新 StatusInfo
的列表,方法是在您的会话上启用该过滤器,然后执行查询:
session.enableFilter( "dispute-with-latest-statusinfo" );
List<Dispute> disputes = session
.createQuery( "FROM Dispute d JOIN FETCH d.statusInfos", Dispute.class )
.getResultList()
为了按照您的要求对结果进行排序:
session.enableFilter( "dispute-with-latest-statusinfo" );
List<Dispute> disputes = session
.createQuery( "FROM Dispute d JOIN FETCH d.statusInfos si ORDER BY si.status DESC", Dispute.class )
.getResultList()
现在,如果您不喜欢在这些情况下使用包含单个元素的 List<StatusInfo>
,您可以添加一个瞬态方法来提供帮助,以便您可以获取对象或获取 null
而不必担心集合语义:
@Transient
public StatusInfo getLatestStatusInfo() {
if ( statusInfos.isEmpty() ) {
return null;
}
else if ( statusInfos.size() == 1 ) {
return statusInfos.get( 0 );
}
else {
// you could add logic here to do the sort in-memory
// for cases where you may have the full collection
// but still want to obtain the last entry ...
}
}
所以我们有 2 个对象,每个映射到一个数据库 table。
public class Dispute {
private Long disputeSeqNo;
private List<StatusInfo> statusInfos;
}
public class StatusInfo {
private Long statusSeqNo;
private Date createdDt;
private String statusCd;
private Dispute dispute;
}
一个争议可以有 0 个或多个与之关联的 StatusInfo。
目前,hibernate 正在为每个 Dispute 返回所有 StatusInfo 对象。虽然在某些情况下这是需要的。但是我有一个用例:
- 我只需要显示每个争议的最新 StatusInfo。
- 此外,在同一个显示器上,我需要能够按最近的 StatusInfo.statusCd 值排序。这种排序需要在数据库中进行,因为我的显示是分页的(使用休眠分页工具)。 (在检索后对数据进行排序确实不是一个选项,因为会有很多行数据。)
我知道使用简单的 SQL 我可以做到这一点,努力将其转换为 HQL。
关于如何使用 HQL 解决这个问题有什么想法吗?我还回来的地方:
List<Dispute>
感谢您的反馈。
谢谢!
您需要做的第一件事是在下面定义一个 Hibernate 过滤器。您可以简单地在 Dispute
class.
@FilterDef( name = "dispute-with-latest-statusinfo" )
接下来您需要在您的 StatusInfo
集合上应用这个命名过滤器,如下所示:
@OneToMany( mappedBy = "dispute" )
@Filter(
name = "dispute-with-latest-statusinfo",
condition = "statusinfo_id = (select max(si.statusinfo_id) from
StatusInfo si WHERE si.dispute_dispute_id = dispute_dispute_id")
private List<StatusInfo> statusInfos;
为了满足您的第一个要求,您可以获得 Dispute
个实例及其最新 StatusInfo
的列表,方法是在您的会话上启用该过滤器,然后执行查询:
session.enableFilter( "dispute-with-latest-statusinfo" );
List<Dispute> disputes = session
.createQuery( "FROM Dispute d JOIN FETCH d.statusInfos", Dispute.class )
.getResultList()
为了按照您的要求对结果进行排序:
session.enableFilter( "dispute-with-latest-statusinfo" );
List<Dispute> disputes = session
.createQuery( "FROM Dispute d JOIN FETCH d.statusInfos si ORDER BY si.status DESC", Dispute.class )
.getResultList()
现在,如果您不喜欢在这些情况下使用包含单个元素的 List<StatusInfo>
,您可以添加一个瞬态方法来提供帮助,以便您可以获取对象或获取 null
而不必担心集合语义:
@Transient
public StatusInfo getLatestStatusInfo() {
if ( statusInfos.isEmpty() ) {
return null;
}
else if ( statusInfos.size() == 1 ) {
return statusInfos.get( 0 );
}
else {
// you could add logic here to do the sort in-memory
// for cases where you may have the full collection
// but still want to obtain the last entry ...
}
}