我面临一个非常令人困惑的情况,我不确定这是不是一个错误。
我正在尝试将PostgreSQL用作Jetty管理的池数据源。 DBCP2.1也用作池管理器。数据源在Jetty上下文配置文件中配置,类似于:
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/</Set>
<Set name="war">
<Property name="jetty.webapps" default="."/>/root.war
</Set>
<Set name="extractWAR">true</Set>
<Set name="copyWebDir">false</Set>
<Set name="configurationDiscovered">true</Set>
<!-- Postgresql connection pool using DBCP2 -->
<New id="ketabakds" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg>
<Ref refid='wac'/>
</Arg>
<Arg>jdbc/dbpool</Arg>
<Arg>
<New class="org.apache.commons.dbcp2.BasicDataSource">
<Set name="driverClassName">org.postgresql.Driver</Set>
<Set name="url">jdbc:postgresql://localhost:5432/pg_databse</Set>
<Set name="username">pg_user</Set>
<Set name="password">pg_pass</Set>
</New>
</Arg>
</New>
</Configure>
然后在我的代码中检索数据源,如下所示:
DataSource source = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/dbpool");
这一切都正常,直到我尝试使用PGobject类在预准备语句上设置任何内容。例如,我有这个代码传递一些JSON:
PGobject jsonObject = new PGobject();
jsonObject.setType(JSON_TYPE);
jsonObject.setValue(json);
statement = aConnection.prepareStatement(
"insert into " +
tableName() +
" (data) values (?)"
);
statement.setObject(1, jsonObject);
statement.executeUpdate();
这里我收到了这个错误:
org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of org.postgresql.util.PGobject. Use setObject() with an explicit Types value to specify the type to use.
at org.postgresql.jdbc.PgPreparedStatement.setObject(PgPreparedStatement.java:1039) ~[postgresql-9.4.1208.jar:9.4.1208]
at org.apache.commons.dbcp2.DelegatingPreparedStatement.setObject(DelegatingPreparedStatement.java:189) ~[commons-dbcp2-2.1.1.jar:2.1.1]
at org.apache.commons.dbcp2.DelegatingPreparedStatement.setObject(DelegatingPreparedStatement.java:189) ~[commons-dbcp2-2.1.1.jar:2.1.1]
我甚至调试到PgPreparedStatement.java:1039,非常有趣的一点是传递的值(名为x)仍然是PGobject类型,但是评估PGobject的x实例返回false。
我怀疑问题是Jetty加载PG的JDBC驱动程序两次。一旦加载上下文配置,第二次加载WAR应用程序本身。因此,有两个PGobject类,即使它们都具有确切的包名称。
我不是码头,但这可能吗?是否有解决方案,以便我可以使用PGobject将值传递给预准备语句?
答案 0 :(得分:1)
好的,我找到了问题的原因。我怀疑PostgreSQL JDBC驱动程序由于上下文配置而被Jetty加载两次,而第二次在Web应用程序中加载。
我通过从Web应用程序中删除依赖项并将其留给jetty来加载应用程序来解决问题。由于我的构建工具是Gradle,这意味着我将web应用程序的postgresql驱动程序的依赖关系设置为compileOnly。