Hibernate、PostgreSQL:如何在数组列中搜索

Hibernate, PostgreSQL: how to search in an array column

我用的是PostgreSQLtableagents。它有一个列 zip_codes character(5)[] 存储代理负责区域的邮政编码。

它存储 agent1 邮政编码 {11111,22222}agent2 邮政编码 {33333}.

我想寻找负责某个特殊区域的所有代理商。

没有 Hibernate 很容易:SELECT * FROM agents WHERE '11111' = ANY (zip_codes) returns agent1.

但是我如何使用 HQL 实现呢?它不知道any。但是如果我改用in,我会得到错误的结果:如果我写select agents from Agents as agents where '{11111}' in (agents.zip_codes),将找不到agent1。如果我改用 '{33333}',则会找到 agent2

当然,我可以使用类似 (in sql) WHERE zip_codes[1] = '11111' OR zip_codes[2] = '11111' 的搜索(PostgreSQL 中的数组从索引 1 开始),但这对于 zip_codes 中的许多条目来说并不方便.

使用 Hibernate 拦截器的解决方法

这不是一个好的解决方案:

编写 hql 查询 select agents from Agents as agents where '11111' in (agents.zip_codes) 并使用 Hibernate 拦截器

public class CustomInterceptor extends EmptyInterceptor {

  @Override
  public String onPrepareStatement(String sql) {
    return sql.replaceAll("\s+in\s*\(", " = any (");
  }
}

你可以这样注册方言

public class MyPostgresSQLDialect extends PostgreSQLDialect {
  public MyPostgresSQLDialect() {
    super();

    this.registerFunction( "array_any", new SQLFunctionTemplate(StandardBasicTypes.INTEGER,"ANY(?1)") );
    this.registerFunction( "array_array", new SQLFunctionTemplate(StandardBasicTypes.INTEGER,"array[?1]") );

  }
}

现在您可以在 hql 中使用

String hql = " from tablename" +
            " where year = :year and month = :month and :version = array_any(versions)";

记得在 sessionFactory 中注册方言

<prop key="hibernate.dialect">com.test.MyPostgresSQLDialect</prop>