带有 @Convert 的 JPQL IN 子句
JPQL IN clause with @Convert
在非规范化 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;
}
记录转换器
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直接不工作
- @公式无效
似乎问题在于记录应该 单引号逗号分隔 而不仅仅是 逗号分隔 因为它们是字符串。 (本机 SQL 查询在这种情况下有效)
问:如何在不更改 RecordsConverter 的情况下使用 JPQL(非本机查询)并希望在没有 JPA 规范的情况下完成这项工作?
我好像受到了影响 Hibernate bug
解决方法是使用集合包装器:
@Data
@Builder
public class MyCollection implements Serializable {
private final Set<String> collection;
}
并更改您的属性转换器:
public class MyConverter implements AttributeConverter<MyCollection, String> {
@Override
public String convertToDatabaseColumn(MyCollection myCollection) {
return String.join(",", myCollection.getCollection());
}
@Override
public MyCollection convertToEntityAttribute(String myCollection) {
return MyCollection.builder()
.collection(Arrays.stream(myCollection.split(",")).collect(Collectors.toSet()))
.build();
}
}
你是模特:
@Entity
@Table(name = "MY_MODEL")
public class MyModel {
@Column(name = "MY_COLLECTION")
@Convert(converter = MyConverter.class)
private MyCollection myCollection;
}
这对我有用。
在非规范化 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;
}
记录转换器
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直接不工作
- @公式无效
似乎问题在于记录应该 单引号逗号分隔 而不仅仅是 逗号分隔 因为它们是字符串。 (本机 SQL 查询在这种情况下有效)
问:如何在不更改 RecordsConverter 的情况下使用 JPQL(非本机查询)并希望在没有 JPA 规范的情况下完成这项工作?
我好像受到了影响 Hibernate bug
解决方法是使用集合包装器:
@Data
@Builder
public class MyCollection implements Serializable {
private final Set<String> collection;
}
并更改您的属性转换器:
public class MyConverter implements AttributeConverter<MyCollection, String> {
@Override
public String convertToDatabaseColumn(MyCollection myCollection) {
return String.join(",", myCollection.getCollection());
}
@Override
public MyCollection convertToEntityAttribute(String myCollection) {
return MyCollection.builder()
.collection(Arrays.stream(myCollection.split(",")).collect(Collectors.toSet()))
.build();
}
}
你是模特:
@Entity
@Table(name = "MY_MODEL")
public class MyModel {
@Column(name = "MY_COLLECTION")
@Convert(converter = MyConverter.class)
private MyCollection myCollection;
}
这对我有用。