【发布时间】:2020-05-11 14:39:54
【问题描述】:
在我的一生中,我不知道如何构造这个 JPA 查询。
我需要找到 在给定的 SyncSendingConfig 下没有传输的事务日志,按 ID 排序。
在 SO 上对其进行研究,我认为应该可以在 SQL 中进行外连接,其中一侧的 ID 为空,如下图所示:
这是我必须使用的实体。
@Entity
public class SyncSendingConfig {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "sendingConfig")
private Set<SyncJob> sendJobs = new HashSet<>();
}
@Entity
public class SyncJob {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sending_config_id")
private SyncSendingConfig sendingConfig;
@ManyToMany(cascade = { CascadeType.ALL })
@JoinTable(
name = "SyncJob_TransactionLog",
joinColumns = { @JoinColumn(name = "sync_job_id") },
inverseJoinColumns = { @JoinColumn(name = "transaction_log_id") }
)
private Set<TransactionLog> transmitted = new HashSet<>();
}
@Entity
public class TransactionLog {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@ManyToMany(mappedBy = "transmitted")
private Set<SyncJob> syncJobs = new HashSet<>();
}
还有我正在尝试编写的 DAO:
public interface SyncSendingConfigDao extends JpaRepository<SyncSendingConfig, Long> {
// TODO: This is the query I'm trying to get to work
/** Returns those transactions that were never sent for the given SyncSenderConfig, ordered by ID */
@Query("SELECT tl FROM SyncJob sj "+
"JOIN SyncSendingConfig ssc ON sj.sendingConfig = ssc.id AND ssc.id= :sendingConfigId "+
"RIGHT JOIN TransactionLog tl on tl.syncJobs = sj "+
"WHERE sj.id is null"
)
Stream<TransactionLog> findTransactionsNotSentForSyncSendingConfigId(@Param("sendingConfigId") long sendingConfigId);
// If this part is relevant, this join shows how I can get only those SyncJobs which are related to the SyncSendingConfig of interest
@Query("SELECT sj FROM SyncJob sj JOIN SyncSendingConfig ssc ON sj.sendingConfig = ssc.id WHERE ssc.id= :sendingConfigId ")
@QueryHints(value = @QueryHint(name = org.hibernate.jpa.QueryHints.HINT_FETCH_SIZE, value = "500"))
Stream<SyncJob> findJobs(@Param("sendingConfigId") long sendingConfigId);
}
上面关于 DAO 的查询显示了我正在尝试做的事情。我真的不确定如何将 SQL 转换为 JPQL ......尤其是在连接条件和顺序上。
更新:
这是我要翻译的确切 SQL 查询。它匹配上面类中由hibernate定义的所有关系。
select tl.*
from sync_job sj
join sync_sending_config ssc
on ssc.id = sj.sending_config_id and ssc.id=2
join sync_job_transaction_log sjtl
on sjtl.sync_job_id = sj.id
RIGHT JOIN transaction_log tl
on tl.id = sjtl.transaction_log_id
where sjtl.sync_job_id is null
当直接运行此查询时,它会返回正在寻找的确切结果。
如果有人能提供帮助,我将不胜感激。我一直在碰壁,试图弄清楚 JPQL 语法。
谢谢
更新 2
使用“@SB”后,JPQL 似乎不支持右连接。由于没有找到如何在 JPQL 中使用左连接(如果可能的话)来编写它,我使用了原生查询:
@Query(value = "select tl.* from sync_job sj "+
"join sync_sending_config ssc on ssc.id = sj.sending_config_id and ssc.id = :sendingConfigId "+
"join sync_job_transaction_log sjtl on sjtl.sync_job_id = sj.id "+
"RIGHT JOIN transaction_log tl on tl.id = sjtl.transaction_log_id "+
"where sjtl.sync_job_id is null",
nativeQuery = true)
@QueryHints(value = @QueryHint(name = org.hibernate.jpa.QueryHints.HINT_FETCH_SIZE, value = "500"))
Stream<TransactionLog> findTransactionsNotSentForSyncSendingConfigId(@Param("sendingConfigId") long sendingConfigId);
【问题讨论】:
-
连接列的另一边是什么? T1 left join config on config.transmitted = ?
-
我的想法是TransactionLog TL可以根据Join Table“SyncJob_TransactionLog”中的TL.id和SJ.id与SyncJob“SJ”进行join。然后限制结果,其中唯一考虑的 SJ 是 SJ.id = SyncSendingConfig.id 其中 SyncSendConfig = id 参数。然后限制 SJ.id 为空的结果。
-
试试吧!让我们看看结果。基本上,两个表之间的连接应该至少在每一侧的一个相关列之间
-
我一直在尝试对查询进行不同的黑客攻击以使其正常工作...我将使用堆栈跟踪更新问题。但是我什至不确定加入表格的顺序,或者语法应该是什么样子,对于 JPQL 来说是新手。
-
只是基于编辑的想法,如果您只能获得与感兴趣的 SyncSendingConfig 相关的 SyncJobs 的列表,那么您可以从 TransactionLog 的 syncJobs 中排除这些?类似的东西 - SELECT tl from TransactionLog tl where t1.syncJobs not in(上面选择了syncJobs)
标签: sql hibernate jpql outer-join