Java 字符串的JPA规范搜索列表包含

Java 字符串的JPA规范搜索列表包含,java,spring,hibernate,jpa,Java,Spring,Hibernate,Jpa,我拥有以下实体: @Entity @Table(name = "my_entity"); public class MyEntity { // some fields @Column(name = "languages") @Convert(converter = StringToListConverter.class) private List<String> languages; } 字段languages包含逗号分隔的值列表EN、FR、NO 我

我拥有以下实体:

@Entity
@Table(name = "my_entity");
public class MyEntity {
    // some fields
    @Column(name = "languages")
    @Convert(converter = StringToListConverter.class)
    private List<String> languages;
}
字段
languages
包含逗号分隔的值列表
EN、FR、NO

我的任务是选择包含某种语言的记录。例如,在本机SQL中,我想使用以下SQL:

SELECT * FROM my_entity e WHERE e.languages LIKE CONCAT('%', 'EN', '%');
我已尝试使用规范来完成此操作:

Specification<MyEntity> specification = (root, query, cb) -> {
    final Path<Collection<String>> langs = root.get("languages");
    // also I tried root.joinList
    return cb.isMember("EN", langs);
};

repository.findAll(specification);
StringToListConverter
如下所示:

@Converter
public class StringToListConverter implements AttributeConverter<List<String>, String> {

@Override
public String convertToDatabaseColumn(List<String> list) {
    if(list==null)
        return null;
    return String.join(",", list);
}

@Override
public List<String> convertToEntityAttribute(String joined) {
    if(joined==null)
        return null;
    return new ArrayList<>(Arrays.asList(joined.split(",")));
}

}
@转换器
公共类StringToListConverter实现AttributeConverter{
@凌驾
公共字符串convertToDatabaseColumn(列表){
if(list==null)
返回null;
返回字符串。join(“,”列表);
}
@凌驾
公共列表convertToEntityAttribute(字符串连接){
if(joined==null)
返回null;
返回新的ArrayList(Arrays.asList(joined.split(“,”));
}
}
存储库:

public class MyEntityRepository extends PagingAndSortingRepository<Address, String>, JpaSpecificationExecutor<MyEntity> {

}
公共类MyEntityRepository扩展了分页和排序存储库,JpaSpecificationExecutor{
}

如何解决此问题?

关于此问题,有一个非常老的开放式hibernate问题:

遗憾的是,我发现的唯一解决办法是对实体中的语言使用二级只读映射,并在规范中使用该映射

@Entity
@Table(name = "my_entity");
public class MyEntity {
    // some fields
    @Column(name = "languages")
    @Convert(converter = StringToListConverter.class)
    private List<String> languages;

    @Column(name = "languages", insertable = false, updatable = false)
    private String languagesString; //No need for setter

}
@实体
@表(name=“我的实体”);
公共类MyEntity{
//一些领域
@列(name=“languages”)
@Convert(converter=StringToListConverter.class)
私人名单语言;
@列(name=“languages”,insertable=false,updateable=false)
私有字符串语言String;//不需要setter
}
标准如下:

Specification<MyEntity> specification = (root, query, cb) -> {
    final Path<String> path = root.get("languagesString");
    return cb.like(path, "%EN%");
};

repository.findAll(specification);
规范=(根、查询、cb)->{
最终路径路径=root.get(“languagesString”);
返回cb.like(路径,“%EN%”);
};
存储库。findAll(规范);

如果您使用的是jpa存储库,那么为什么不使用上面提到的本机查询呢?也可以添加一些东西,从我的实体e中选择*,其中e.languages like%:language%此处language将是一个变量,您将在此处传递该变量以替换本机查询中的language字段。请显示您的存储库类中编写此查询的位置?@GauravRai1512我从上面的示例中删除了一些可以正常工作的条件。我无法动态构建本机SQL@GauravRai1512我已经添加了存储库
@Entity
@Table(name = "my_entity");
public class MyEntity {
    // some fields
    @Column(name = "languages")
    @Convert(converter = StringToListConverter.class)
    private List<String> languages;

    @Column(name = "languages", insertable = false, updatable = false)
    private String languagesString; //No need for setter

}
Specification<MyEntity> specification = (root, query, cb) -> {
    final Path<String> path = root.get("languagesString");
    return cb.like(path, "%EN%");
};

repository.findAll(specification);