我正在使用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;
}
查询是“update table_name set array_column =?where id_user =?and id_device =?”。 我得到了这个例外:
org.springframework.dao.DataIntegrityViolationException:PreparedStatementCallback; SQL [更新acotel_msp.users_mau设置denied_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语法[更新用户设置denied_sub_client =? id_users =?和id_device =?];嵌套异常是org.postgresql.util.PSQLException:无法将java.util.ArrayList的实例强制转换为Types.ARRAY
尝试第二种解决方案我有这个:
org.springframework.jdbc.BadSqlGrammarException:PreparedStatementCallback;错误的SQL语法[更新用户设置denied_sub_client =? id_users =?和id_device =?];嵌套异常是org.postgresql.util.PSQLException:无法强制转换[Ljava.lang.Object;输入Types.ARRAY
我想我需要一个java.sql.Array实例,但是如何使用JdbcTemplate创建它呢?
答案 0 :(得分:2)
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;
}
});
答案 1 :(得分:1)
参数类型和参数不匹配。
尝试更改参数类型顺序
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 })
看看它是否有效
答案 2 :(得分:1)
http://valgogtech.blogspot.com/2009/02/passing-arrays-to-postgresql-database.html解释了如何创建java.sql.Array postgresql 基本上Array.getBaseTypeName应该返回int,而Array.toString应该以“{1,2,3}”格式返回数组内容
创建阵列后,您可以使用 preparedstatement.setArray(...)进行设置 来自PreparedStatementCreator,例如
jdbcTemplate.update(
new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
祝你好运..
答案 3 :(得分:1)
这个解决方案是一种使用postgreSQL内置函数的解决方法,这绝对适用于我。
1)将字符串数组转换为逗号分隔字符串
如果您使用的是Java8,那就非常简单了。其他选项是here
String commaSeparatedString = String.join(",",stringArray); // Java8 feature
2)PostgreSQL内置函数string_to_array()
你可以找到其他postgreSQL数组函数here
// 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
答案 4 :(得分:0)
到目前为止,我发现的最干净的方法是先将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
答案 5 :(得分:0)
经过很多尝试后,我们决定使用一个小助手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;
}
}
此代码在公共领域中提供
答案 6 :(得分:-1)
private string fill_form(string output_file)
{
using (PdfReader _pdfReader = new PdfReader(FormPath))
{
using (PdfStamper _pdfStamper = new PdfStamper(_pdfReader, new FileStream(output_file, FileMode.Create)))
{
_pdfStamper.AcroFields.GenerateAppearances = true;
foreach (var _field in _pdfStamper.AcroFields.Fields)
foreach (TemplateField _spField in _lstFields)
{
if (_field.Key.Equals(_spField.Name))
{
switch (_spField.Type )
{
case TemplateFieldType.Text:
_pdfStamper.AcroFields.SetField(_field.Key, _spField.Value);
break;
case TemplateFieldType.Checkbox:
if (_spField.Value == _spField.OnValue)
_pdfStamper.AcroFields.SetField(_field.Key, _spField.OnValue);
else
_pdfStamper.AcroFields.SetField(_field.Key, _spField.OffValue);
break;
}
}
}
_pdfStamper.FormFlattening = true;
}
}
return output_file;
}