【发布时间】:2019-04-12 22:54:13
【问题描述】:
我编写了以下查询以在 Spring JpaRespository 中使用:
private const val SEARCH =
"SELECT vf " +
"FROM VideoFile vf " +
"LEFT JOIN vf.stars st " +
"LEFT JOIN vf.categories c " +
"LEFT JOIN vf.series se " +
"WHERE (:searchText IS NULL OR (" +
"vf.fileName LIKE :searchText OR vf.displayName LIKE :searchText OR vf.description LIKE :searchText)) " +
"AND (:seriesId IS NULL OR se.seriesId = :seriesId) " +
"AND (:starId IS NULL OR st.starId = :starId) " +
"AND (:categoryId IS NULL OR c.categoryId = :categoryId)"
这是基于我之前测试过的 SQL 查询,但使用 JPQL 编写。我将在下面包含我的实体(Kotlin),以便我将要解释的内容更有意义:
@Entity
@Table(name = "video_files")
data class VideoFile(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var fileId: Long = 0,
@Column(unique = true)
var fileName: String = "",
var displayName: String = "",
var description: String = "",
var lastModified: LocalDateTime = DEFAULT_TIMESTAMP,
@JsonIgnore
var lastScanTimestamp: LocalDateTime = DEFAULT_TIMESTAMP,
@Column(columnDefinition = "int default 0")
var viewCount: Int = 0,
@ManyToMany (fetch = FetchType.EAGER)
@JoinTable(name = "file_categories",
joinColumns = [JoinColumn(name = "file_id")],
inverseJoinColumns = [JoinColumn(name = "category_id")])
var categories: Set<Category> = HashSet(),
@ManyToMany (fetch = FetchType.EAGER)
@JoinTable(name = "file_series",
joinColumns = [JoinColumn(name = "file_id")],
inverseJoinColumns = [JoinColumn(name = "series_id")])
var series: Set<Series> = HashSet(),
@ManyToMany (fetch = FetchType.EAGER)
@JoinTable(name = "file_stars",
joinColumns = [JoinColumn(name = "file_id")],
inverseJoinColumns = [JoinColumn(name = "star_id")])
var stars: Set<Star> = HashSet()
)
因此,我的 VideoFile 实体与 Category、Series 和 Star 实体之间存在多对多关系。我正在编写的查询是尝试获取与某些类别、系列、明星等连接的所有 VideoFile。
我现在的查询返回重复记录,我相信是因为左连接。因为 VideoFile 与多个类别匹配,所以我多次返回相同的记录。
我精通 SQL,但我还是 JPQL 的新手。我希望能得到一些帮助来重构它,以便它只按加入的实体过滤 VideoFiles,而不是返回额外的记录。
【问题讨论】: