Postgres SQLクエリはファイルに格納され、PHPから使用されています。この作業は、PHPをJavaに置き換えることです。移行パスを短くするために、「そのまま」のクエリを再利用したいと考えています。私は配列パラメータを動作させることができません。ここでJPA/Hibernateネイティブクエリ(配列パラメータ)でPostgres any-clauseを使用する方法
は、クエリの例です:彼らは配列型を期待しているため
update user_devices
set some_date = now()
where some_id in (
select distinct some_id from user_devices
where user_id = any(:userIDs) and device_id = any(:deviceIDs)
and exists (select 1 from users where user_id = any(:userIDs) and customer_id = :customerID)
);
は、問題を引き起こす「任意の」の句を、注意してください。 これは、我々はPHPからそれらを使用する方法です。だから、「{111222}」の配列型は次のようになり、パラメータとして
$this->allValues['userIDs'] = '{' . implode (",", $userIdNodes) . '}';
$this->allValues['deviceIDs'] = '{' . implode (",", $deviceIdNodes) . '}';
$this->allValues['customerID'] = customerID;
$this->db->runQuery ($this->getQuery ('my_query'), $this->allValues);
。
これは私がJavaで試したものです:
Caused by: org.hibernate.HibernateException: Could not determine a type for class: org.postgresql.jdbc4.Jdbc4Array
at org.hibernate.internal.AbstractQueryImpl.guessType(AbstractQueryImpl.java:550)
at org.hibernate.internal.AbstractQueryImpl.guessType(AbstractQueryImpl.java:534)
at org.hibernate.internal.AbstractQueryImpl.determineType(AbstractQueryImpl.java:519)
at org.hibernate.internal.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:487)
at org.hibernate.jpa.internal.QueryImpl$ParameterRegistrationImpl.bindValue(QueryImpl.java:247)
at org.hibernate.
または: "のtoArray" メソッドを使用している場合 :これらの
Integer customerID = 1;
int[] userIDs = new int[]{111,222};
int[] deviceIDs= new int[]{333,444};
//List<Integer> userIDs = Arrays.asList(111,222);
//List<Integer> deviceIDs= Arrays.asList(333,444);
//java.sql.Array userIDs = toArray("integer", new int[]{111,222}));
//java.sql.Array deviceIDs= toArray("integer", new int[]{333,444}));
//java.sql.Array userIDs = toArray("integer", Arrays.asList(111,222)));
//java.sql.Array deviceIDs= toArray("integer", Arrays.asList(333,444)));
//String userIDs = "{111,222}";
//String deviceIDs= "{333,444}";
//String userIDs = "ARRAY[111,222]";
//String deviceIDs= "ARRAY[333,444]";
Query nativeQuery = em.createNativeQuery(queryString);
nativeQuery.setParameter("userIDs", userIDs);
nativeQuery.setParameter("deviceIDs", deviceIDs);
nativeQuery.setParameter("customerID", customerID);
//nativeQuery.setParameter(createParameter("userIDs",java.sql.Array.class), userIDs);
//nativeQuery.setParameter(createParameter("userIDs",java.sql.Array.class), deviceIDs);
//nativeQuery.setParameter(createParameter("customerID", Integer.class), customerID);
query.executeUpdate();
//[...]
private Array toArray(String typeName, Object... elements) {
Session session = em.unwrap(Session.class); // ATTENTION! This is Hibernate-specific!
final AtomicReference<Array> aRef = new AtomicReference<>();
session.doWork((c) -> {
aRef.set(c.createArrayOf(typeName, elements));
});
return aRef.get();
}
private <T> Parameter<T> createParameter(final String name, final Class<?> clazz) {
return new Parameter<T>() {
@Override
public String getName() {
return name;
}
@Override
public Integer getPosition() {
return null; // not used
}
@Override
public Class<T> getParameterType() {
return (Class<T>) clazz;
}
};
}
どれも、私はこれらの例外のいずれかを取得します動作しませんint []やStringsを使用する場合は、
Caused by: org.postgresql.util.PSQLException: ERROR: op ANY/ALL (array) requires array on right side
Position: 137
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2270)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1998)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:570)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:420)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:366)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.postgresql.ds.jdbc23.AbstractJdbc23PooledConnection$StatementHandler.invoke(AbstractJdbc23PooledConnection.java:453)
at com.sun.proxy.$Proxy274.executeUpdate(Unknown Source)
at com.sun.gjc.spi.base.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:125)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)
jpa.spi.BaseQueryImpl.setParameter(BaseQueryImpl.java:582)
両方のAPIがデータベースに話しているとき、Wiresharkのは、私がこれを見つけた:
Image: Comparison of database calls with Wireshark
select oid, typname from pg_type where oid in (0, 23, 1043) order by oid;
oid |typname
------+-------
23 |int4
1043 |varchar
を誰もがJPAのEntityManagerのためのバックエンドとして休止状態を使用して、ネイティブクエリで配列パラメータを使用するように管理していますか?もしそうなら:どのように?