带有 @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),即使:

似乎问题在于记录应该 单引号逗号分隔 而不仅仅是 逗号分隔 因为它们是字符串。 (本机 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;
}

这对我有用。