我正在使用JPA Hibernate的本地查询对PostgreSQL进行插入或更新("upsert"),这取决于对象是否存在。代码看起来像这样。
val values: String = items.joinToString(", ", transform = this::convertItemToSqlValue)
val query = """
insert into item (field1, field2)
values $values
on conflict on constraint item_pkey
do update set
field1 = excluded.field1,
field2 = excluded.field2
"""
entityManager.createNativeQuery(query).executeUpdate()
函数 convertItemToSqlValue
创建一个字符串,其形式为 ('value a', 123)
.
一个位置参数(values ?
)没有工作(并导致语法错误)。
我怎样才能防止这种状态下的SQL注入?
从用户输入动态地构建SQL语句不是最好的主意。最好是使用准备好的语句。然而,在这种情况下,似乎没有一个简单的方法来执行JPA EntityManager的补丁更新。
通过JDBC可以设置多个值。下面的例子展示了如何使用 Spring的JdbcTemplate:
val items: List<Item> = ...
val statement =
"""
insert into item (field1, field2)
values (?,?)
on conflict on constraint arbeit_pkey
do update set
field1 = excluded.field1,
field2 = excluded.field2
"""
jdbcTemplate.batchUpdate(
statement,
object : BatchPreparedStatementSetter {
override fun setValues(statement: PreparedStatement, index: Int) {
val item = items[index]
statement.setString(1, item.field1)
statement.setInt(2, item.field2)
}
override fun getBatchSize(): Int = items.size
}
)