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>
我用的是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>