【发布时间】:2021-01-11 15:06:03
【问题描述】:
在非规范化 PostgreSQL 数据库中:“Document”和“Record”两个表
Document 有一个 id 和一个逗号分隔的列 recodeIds
--------------------------------------
| id (VARCHAR) | recordIds (VARCHAR) |
--------------------------------------
| 1 | 3,1 |
| 2 | 2 |
--------------------------------------
记录有id和名字
---------------------------------
| id (VARCHAR) | name (VARCHAR) |
---------------------------------
| 1 | X |
| 2 | Y |
| 3 | Z |
---------------------------------
DocumentModel 与 @Convert
@Entity
@Table(name = "Document")
public class DocumentModel {
@Id
@Column(name = "id")
private String id;
@Column(name = "recodeIds")
@Convert(converter = RecordsConverter.class)
private Set<String> records;
}
RecordsConverter
public class RecordsConverter implements AttributeConverter<Set<String>, String> {
@Override
public String convertToDatabaseColumn(Set<String> recordTypes) {
return String.join(",", recordTypes);
}
@Override
public Set<String> convertToEntityAttribute(String recordTypes) {
return Arrays.stream(recordTypes.split(",")).collect(Collectors.toSet());
}
}
JPQL现在我正在尝试在@Query 中使用记录
@Query("SELECT D.id, R.name)"
+ " FROM DocumentModel D"
+ " JOIN RecordModel R"
+ " ON R.id IN D.records"
+ " WHERE D.id = :docId"
这仅适用于 recordIds 具有单一值(例如:docId = 2)
如果 recordIds 有多个值(例如:docId = 1),即使:
- 嵌套 SELECT 不起作用
- 带和不带 () 的 IN 子句不起作用
- MEMBER OF 子句不起作用
- 导致本机 SQL 直接不起作用
- @Formula 不起作用
问题似乎在于记录应该是单引号逗号分隔,而不仅仅是逗号分隔,因为它们是字符串。 (本机 SQL 查询在这种情况下有效)
问:如何在不更改 RecordsConverter 并且希望不使用 JPA 规范的情况下使用 JPQL(非本地查询)来完成这项工作?
【问题讨论】:
-
解决这个问题的最好方法是规范化你的数据模型。将逗号分隔的值存储在单个列中是一个巨大的错误
-
你是对的,但客户拒绝了:/
-
@AhmedGhoneim 它是否适用于您的 JPQL 的 sql 查询模拟?
-
没有。它仅适用于单引号逗号分隔值
-
您可以创建一个显示
document表的规范化版本的视图。然后您使用常规连接将其与Record表结合起来
标签: postgresql hibernate spring-data-jpa jpql