Postgresql JPA/Hibernate自定义查询和Postgres枚举列表

Postgresql JPA/Hibernate自定义查询和Postgres枚举列表,postgresql,hibernate,jpa,kotlin,enums,Postgresql,Hibernate,Jpa,Kotlin,Enums,我有一个实体Company,其类型由enumCompanyType表示。 数据库是Postgres,在那里表示为枚举类型。 我使用JPA/Hibernate及其存储库。 请注意,我是JPA、Hibernate和Kotlin的新手 我正在尝试创建自定义的@Query,在这里我需要选择类型(枚举)在可能类型列表中的公司。然而,在SQL中的类型转换和/或@Query的语法方面,我遇到了各种错误 Kotlin中数据类公司的主要部分(未复制任何其他属性,包括id): Kotlin中的枚举CompanyTy

我有一个实体
Company
,其类型由enum
CompanyType
表示。 数据库是Postgres,在那里表示为枚举类型。 我使用JPA/Hibernate及其存储库。 请注意,我是JPA、Hibernate和Kotlin的新手

我正在尝试创建自定义的
@Query
,在这里我需要选择类型(枚举)在可能类型列表中的公司。然而,在SQL中的类型转换和/或
@Query
的语法方面,我遇到了各种错误

Kotlin中数据类
公司
的主要部分(未复制任何其他属性,包括id):

Kotlin中的枚举
CompanyType

enum class CompanyType(value: Int) {
    BUSINESS(1),
    TOWN(2),
    NONPROFIT(3),
    RESEARCH(4),
    OTHER(5)
}
Postgres中的枚举
公司类型

CREATE TYPE public.company_type AS ENUM (
    'BUSINESS',
    'TOWN',
    'NONPROFIT',
    'RESEARCH',
    'OTHER'
);
CREATE CAST (character varying AS public.company_type) WITH INOUT AS ASSIGNMENT;
JPA存储库与我的初始尝试:

@Repository
interface CompanyDAO : PagingAndSortingRepository<Company> {

    @Query("SELECT c FROM #{#entityName} c " +
        "WHERE c.type IN ?1"
    )
    fun findAllByTypeIn(types: List<CompanyType>, pageable: Pageable): Page<Company>
}
所以我试着去投,但不知道到底是怎么投的

    @Query("SELECT c FROM #{#entityName} c " +
        "WHERE c.type IN cast(?1 AS company_type[])"
    )
导致编译时出错:

antlr.MismatchedTokenException: expecting EOF, found ')'
努力

    @Query("SELECT c FROM #{#entityName} c " +
        "WHERE c.type IN ?1\\:\\:company_type[]"
    )

导致

org.hibernate.QueryException: unexpected char: '\'

如何创建这样的查询,以获取枚举列表并返回值等于列表中任何项的实体?

此错误来自Postgres:

错误:运算符不存在:公司类型=字符变化

要解决这个问题,您可以在Postgres中为company_类型创建一个自定义运算符,而不更改代码中的任何内容。像这样:

CREATE FUNCTION ctype_compare(company_type, text)
RETURNS boolean
AS '
select cast($1 as text) = $2;
'
LANGUAGE sql IMMUTABLE;

CREATE OPERATOR = (
    leftarg = company_type,
    rightarg = text,
    procedure = company_type_compare
);
这样,您实际上可以删除@Query,Hibernate将做正确的事情。如果无法创建自定义运算符,可能是因为您没有正确的权限,则必须将查询更改为:

    @Query("SELECT c FROM #{#entityName} c " +
        "WHERE cast (c.type as text) IN ?1")
然后必须将参数类型固定为字符串

    Page<Company> findAllByTypeIn(List<String> types, Pageable pageable);
Page findAllByTypeIn(列表类型,可分页);
要调用DAO方法,请传递正确的类型:

    List<String> types = new ArrayList();
    types.add(CompanyType.OTHER.toString());
    types.add(CompanyType.BUSINESS.toString());

    Page<Company> companies = dao.findAllByTypeIn(types, Pageable.unpaged());
List types=new ArrayList();
add(CompanyType.OTHER.toString());
添加(CompanyType.BUSINESS.toString());
Page companys=dao.findAllByTypeIn(类型,Pageable.unpaged());

我是用Java做的,不是Kotlin。但是它应该适合您。

将强制转换创建为隐式而不是赋值,这样它也可以用于比较吗

使用INOUT作为隐式创建演员阵容(角色随天数变化)

    Page<Company> findAllByTypeIn(List<String> types, Pageable pageable);
    List<String> types = new ArrayList();
    types.add(CompanyType.OTHER.toString());
    types.add(CompanyType.BUSINESS.toString());

    Page<Company> companies = dao.findAllByTypeIn(types, Pageable.unpaged());