[英]How to update a postgresql array column with spring JdbcTemplate?
我使用的是Spring JdbcTemplate,並且卡在查詢中會更新實際上是int數組的列。 該數據庫是postgres 8.3.7。 這是我正在使用的代碼:
public int setUsersArray(int idUser, int idDevice, Collection<Integer> ids) {
int update = -666;
int[] tipi = new int[3];
tipi[0] = java.sql.Types.INTEGER;
tipi[1] = java.sql.Types.INTEGER;
tipi[2] = java.sql.Types.ARRAY;
try {
update = this.jdbcTemplate.update(setUsersArrayQuery, new Object[] {
ids, idUser, idDevice }, tipi);
} catch (Exception e) {
e.printStackTrace();
}
return update;
}
查詢是“更新table_name設置array_column =?,其中id_user =?和id_device =?”。 我得到這個例外:
org.springframework.dao.DataIntegrityViolationException:PreparedStatementCallback; SQL [更新acotel_msp.users_mau設置否認_sub_client =嗎? 其中id_users =? 和id_mau =?]; 列索引超出范圍:4,列數:3; 嵌套的異常是org.postgresql.util.PSQLException:列索引超出范圍:4,列數:3。
原因:org.postgresql.util.PSQLException:列索引超出范圍:4,列數:3。
我已經研究過Spring JDBC模板文檔,但是我找不到任何幫助,我會一直尋找,無論如何有人會指出我正確的方向嗎? 謝謝!
編輯:
顯然訂單錯了,我的錯...
我嘗試了兩種解決方案,第一種情況是:
org.springframework.jdbc.BadSqlGrammarException:PreparedStatementCallback; 錯誤的SQL語法[更新用戶設置為deny_sub_client =? 其中id_users =? 和id_device =?]; 嵌套的異常是org.postgresql.util.PSQLException:無法將java.util.ArrayList的實例強制轉換為Types.ARRAY。
嘗試第二個解決方案,我有這個:
org.springframework.jdbc.BadSqlGrammarException:PreparedStatementCallback; 錯誤的SQL語法[更新用戶設置為deny_sub_client =? 其中id_users =? 和id_device =?]; 嵌套的異常是org.postgresql.util.PSQLException:無法轉換[Ljava.lang.Object; 鍵入Types.ARRAY
我想我需要一個java.sql.Array實例,但是如何使用JdbcTemplate創建它呢?
private static final String ARRAY_DATATYPE = "int4";
private static final String SQL_UPDATE = "UPDATE foo SET arr = ? WHERE d = ?";
final Integer[] existing = ...;
final DateTime dt = ...;
getJdbcTemplate().update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(final Connection con) throws SQLException {
final PreparedStatement ret = con.prepareStatement(SQL_UPDATE);
ret.setArray(1, con.createArrayOf(ARRAY_DATATYPE, existing));
ret.setDate(2, new java.sql.Date(dt.getMillis()));
return ret;
}
});
經過許多嘗試之后,我們決定使用一個小助手ArraySqlValue為Java Array Types創建Spring SqlValue對象。
用法是這樣的
jdbcTemplate.update(
"UPDATE sometable SET arraycolumn = ?",
ArraySqlValue.create(arrayValue))
ArraySqlValue也可以在MapSqlParameterSource中使用,與NamedParameterJdbcTemplate一起使用。
import static com.google.common.base.Preconditions.checkNotNull;
import java.sql.Array;
import java.sql.JDBCType;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Locale;
import org.springframework.jdbc.core.StatementCreatorUtils;
import org.springframework.jdbc.support.SqlValue;
public class ArraySqlValue implements SqlValue {
private final Object[] arr;
private final String dbTypeName;
public static ArraySqlValue create(final Object[] arr) {
return new ArraySqlValue(arr, determineDbTypeName(arr));
}
public static ArraySqlValue create(final Object[] arr, final String dbTypeName) {
return new ArraySqlValue(arr, dbTypeName);
}
private ArraySqlValue(final Object[] arr, final String dbTypeName) {
this.arr = checkNotNull(arr);
this.dbTypeName = checkNotNull(dbTypeName);
}
@Override
public void setValue(final PreparedStatement ps, final int paramIndex) throws SQLException {
final Array arrayValue = ps.getConnection().createArrayOf(dbTypeName, arr);
ps.setArray(paramIndex, arrayValue);
}
@Override
public void cleanup() {}
private static String determineDbTypeName(final Object[] arr) {
// use Spring Utils similar to normal JdbcTemplate inner workings
final int sqlParameterType =
StatementCreatorUtils.javaTypeToSqlParameterType(arr.getClass().getComponentType());
final JDBCType jdbcTypeToUse = JDBCType.valueOf(sqlParameterType);
// lowercasing typename for Postgres
final String typeNameToUse = jdbcTypeToUse.getName().toLowerCase(Locale.US);
return typeNameToUse;
}
}
此代碼在公共領域中提供
參數類型和參數不匹配。
嘗試更改參數類型順序
int[] tipi = new int[3];
tipi[0] = java.sql.Types.ARRAY;
tipi[1] = java.sql.Types.INTEGER;
tipi[2] = java.sql.Types.INTEGER;
或使用
update = this.jdbcTemplate.update(setUsersArrayQuery, new Object[] {
ids.toArray(), idUser, idDevice })
看看是否可行
http://valgogtech.blogspot.com/2009/02/passing-arrays-to-postgresql-database.html解釋了如何創建java.sql.Array postgresql,基本上Array.getBaseTypeName應該返回int,Array.toString應該返回數組“ {1,2,3}”格式的內容
創建數組后,可以使用PreparedStatementCreator中的preparestatement.setArray (...)進行設置,例如
jdbcTemplate.update(
new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
祝好運 ..
這個解決方案是使用postgreSQL內置函數的一種解決方法,它肯定對我有用。
1)將字符串數組轉換為逗號分隔的字符串
如果您使用的是Java8,則非常簡單。 其他選項在這里
String commaSeparatedString = String.join(",",stringArray); // Java8 feature
2)PostgreSQL內置函數string_to_array()
你可以在這里找到其他的postgreSQL數組函數
// tableName ( name text, string_array_column_name text[] )
String query = "insert into tableName(name,string_array_column_name ) values(?, string_to_array(?,',') )";
int[] types = new int[] { Types.VARCHAR, Types.VARCHAR};
Object[] psParams = new Object[] {"Dhruvil Thaker",commaSeparatedString };
jdbcTemplate.batchUpdate(query, psParams ,types); // assuming you have jdbctemplate instance
到目前為止,我發現的最干凈的方法是先將Collection
轉換為Integer[]
,然后使用Connection
將其轉換為Array
。
Integer[] idArray = ids.toArray(new Integer[0]);
Array idSqlArray = jdbcTemplate.execute(
(Connection c) -> c.createArrayOf(JDBCType.INTEGER.getName(), idArray)
);
update = this.jdbcTemplate.update(setUsersArrayQuery, new Object[] {
idSqlArray, idUser, idDevice })
這基於文檔中的信息: https : //jdbc.postgresql.org/documentation/head/arrays.html
java.sql.Array intArray = connection.createArrayOf("int", existing);
List<Object> values= new ArrayList<Object>();
values.add(intArray);
values.add(dt);
getJdbcTemplate().update(SQL_UPDATE,values);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.