[英]Null pointer exception when inserting row into Postgres
我在Postgres中查询表,以查看是否存在具有主键值匹配给定Map
的行的行。 如果没有结果,我想插入一个新行。 当我使用创建准备好的语句并显式设置所有列值的标准JDBC路线时,可以做到这一点,但是我希望在Groovy的Sql
类的帮助下使用更通用的方法。
这是我的插入语句(主键列为前三列):
insert into MY_TABLE
(contract_month, contract_year, publish_date, open, high, low)
values
(10, 2015, 2015-09-15 00:00:00.0, 46.65, 46.9, 45.98)
问题是,我在插入一行后就从Postgres驱动程序中获取了NullPointerException
:
Exception in thread "main" java.lang.NullPointerException
at org.postgresql.core.v3.SimpleParameterList.setNull(SimpleParameterList.java:142)
at org.postgresql.jdbc2.AbstractJdbc2Statement.setNull(AbstractJdbc2Statement.java:1259)
at org.postgresql.jdbc3.AbstractJdbc3Statement.setNull(AbstractJdbc3Statement.java:1499)
at org.postgresql.jdbc4.AbstractJdbc4Statement.setNull(AbstractJdbc4Statement.java:85)
at org.postgresql.jdbc2.AbstractJdbc2Statement.setObject(AbstractJdbc2Statement.java:2092)
at org.postgresql.jdbc3g.AbstractJdbc3gStatement.setObject(AbstractJdbc3gStatement.java:38)
at org.postgresql.jdbc4.AbstractJdbc4Statement.setObject(AbstractJdbc4Statement.java:48)
深入研究它,我发现在org.postgresql.core.v3.SimpleParameterList
类中一个名为ProtoConnection
的对象为null。 我究竟做错了什么?
这是创建Sql
对象的包装代码:
private Main() {
final def headers = new HashMap<Integer, String>()
final def record = new HashMap<String, Object>()
Sql.withInstance(/* my db */) { final Sql sql ->
sql.withBatch {
new URL(/* my url */).withReader {
it.readLines().each {
if (headers.isEmpty()) {
setHeaders it, headers
}
else {
processRecord it, headers, record
storeRecord sql, record
}
}
}
}
}
}
这就是数据库逻辑。 错误发生在最后一行:
def storeRecord = { final Sql sql, final Map<String, Object> record ->
final def connection = sql.connection
final def metadata = connection.metaData
final def columns = metadata.getColumns(null, null, MY_TABLE, null).with {
final def result = []
while (it.next()) {
result << it.getString(4)
}
result
}
final def primaryKeys = metadata.getPrimaryKeys(null, null, MY_TABLE).with {
final def result = []
while (it.next()) {
result << it.getString(4)
}
result
}
final def whereClause = primaryKeys.collect { final String pk ->
"$pk = ?.$pk"
}
final def select = """
select ${columns.join(', ')}
from MY_TABLE
where ${whereClause.join(' and ')}
"""
final def row = sql.firstRow(select, record)
if (row) {
println "Updating"
// Not implemented yet
}
else {
println "Inserting record: $record"
final def insert = """
insert into MY_TABLE
(${columns.findAll { null != record[it] }.join(", ")})
values
(${columns.findAll { null != record[it] }.collect { record[it] }.join(", ")})
"""
println insert
sql.executeInsert(insert, record)
}
我的代码在某些方面做错了。 首先,我没有将记录映射中的字符串对象转换为适当的JDBC类型。 这解释了为什么我能够像以前一样在此处进行转换,并通过标准的准备好的语句路由插入记录,而在过渡到Groovy的API时却忽略了它。
解决此问题后,我得到一个错误, hstore
不支持hstore
扩展。 这可以通过在Postgres中执行create extension hstore
来解决。
最后,我收到索引超出范围错误。 这是由于我的代码中存在一个愚蠢的错误,我在我的插入语句中设置了值,而不是让API填充了参数。 您现在可以在插入语句的最后一行中看到此修复程序:
final def insert = """
insert into MY_TABLE
(${columns.join(', ')})
values
(${columns.collect { "?.$it" }.join(', ')})
"""
sql.executeInsert(insert, record)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.