【问题标题】:Datanucleus + PostgreSQL not escaping backslashesDatanucleus + PostgreSQL 没有转义反斜杠
【发布时间】:2011-12-15 16:26:13
【问题描述】:

我试图找出 Datanucleus 中的查询出错的地方(由 Postgres DB 支持)。当表达式包含反斜杠时,即使是简单的查询也会失败。但是,我的印象是 JDO/Datanucleus 应该抽象出手动转义参数到查询的需要,就像 PreparedStatement 对纯 JDBC 所做的那样。

这是一个独立的例子:

package somepkg;

import org.datanucleus.api.jdo.JDOPersistenceManager;

import javax.jdo.*;
import javax.jdo.annotations.*;
import java.util.*;

@PersistenceCapable
public final class MyPersistentObject {

    @Persistent(valueStrategy = IdGeneratorStrategy.INCREMENT)
    @PrimaryKey
    private long id;

    @Persistent
    private String value;

    public MyPersistentObject(String value) {
        this.value = value;
    }

    public static void main(String... args) {
        JDOPersistenceManager pm = (JDOPersistenceManager)
                JDOHelper.getPersistenceManagerFactory(datanucleusProperties())
                        .getPersistenceManager();

        //seems to be a problem with values that contain a backspace
        String value = "\\";

        //store (works fine)
        Transaction tx = pm.currentTransaction();
        tx.begin();
        MyPersistentObject objectToStore = new MyPersistentObject(value);
        pm.makePersistent(objectToStore);
        tx.commit();

        //fetch (fails)
        MyPersistentObject fetchedObject = pm
                .newTypesafeQuery(MyPersistentObject.class)
                .filter(QMyPersistentObject.candidate().value.eq(value))
                .executeUnique();

        System.out.println(fetchedObject);
    }

    private static Map<String, String> datanucleusProperties() {
        Map<String, String> datanucleusProperties = new HashMap<String, String>();

        datanucleusProperties.put("javax.jdo.option.ConnectionDriverName", "org.postgresql.Driver");
        datanucleusProperties.put("javax.jdo.option.ConnectionURL", "jdbc:postgresql:test");
        datanucleusProperties.put("javax.jdo.option.ConnectionUserName", "postgres");
        datanucleusProperties.put("javax.jdo.option.ConnectionPassword", "");
        datanucleusProperties.put("datanucleus.autoCreateSchema", "true");
        datanucleusProperties.put("datanucleus.validateTables", "false");
        datanucleusProperties.put("datanucleus.validateConstraints", "false");
        return datanucleusProperties;
    }
}

QMyPersistentObject 是通过运行注释处理器生成的。失败并显示以下消息:

Exception in thread "main" javax.jdo.JDOException: Exception thrown when executing query
at org.datanucleus.api.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:567)
at org.datanucleus.api.jdo.query.JDOTypesafeQuery.executeInternalQuery(JDOTypesafeQuery.java:946)
at org.datanucleus.api.jdo.query.JDOTypesafeQuery.executeUnique(JDOTypesafeQuery.java:770)
at somepkg.MyPersistentObject.main(MyPersistentObject.java:52)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
NestedThrowablesStackTrace:
org.postgresql.util.PSQLException: ERROR: unterminated quoted string at or near "'\'"
Position: 128
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2102)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1835)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:500)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:388)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:273)
at org.datanucleus.store.rdbms.datasource.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.datanucleus.store.rdbms.datasource.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.datanucleus.store.rdbms.SQLController.executeStatementQuery(SQLController.java:465)
at org.datanucleus.store.rdbms.query.JDOQLQuery.performExecute(JDOQLQuery.java:625)
at org.datanucleus.store.query.Query.executeQuery(Query.java:1789)
at org.datanucleus.store.query.Query.executeWithArray(Query.java:1665)
at org.datanucleus.store.query.Query.execute(Query.java:1638)
at org.datanucleus.api.jdo.query.JDOTypesafeQuery.executeInternalQuery(JDOTypesafeQuery.java:936)
at org.datanucleus.api.jdo.query.JDOTypesafeQuery.executeUnique(JDOTypesafeQuery.java:770)
at somepkg.MyPersistentObject.main(MyPersistentObject.java:52)

是否有人对 JDO 或 Datanucleus 有足够的了解,知道我在查询时是否需要采取额外的步骤来逃避内容?如果不是(正如我假设的那样),我想这是 Datanucleus 或 Postgres JDBC 驱动程序中的错误?

【问题讨论】:

    标签: java postgresql jdo datanucleus


    【解决方案1】:

    为什么不把一个参数放在那里(而不是硬编码值,然后得到后续问题),然后将它作为一个?传递给JDBC驱动程序。即 JDBC 总是建议处理此类事情的方式

    【讨论】:

    • 感谢您的回复。所以您是说使用 BooleanExpression 不会为您转义文字?我原以为这是最终开发人员不需要担心的事情,因为我不是制作 SQL 的人。我对 DN 的理解是,我不必与 JDBC 进行太多交互。你能给我指出一个描述你在说什么的资源吗?
    • 如果用户执行“SELECT FROM mydomain.MyClass WHERE field ==” + value 的标准 JDOQL;然后他们必须自己处理任何斜线等。这同样适用于类型安全的 JDOQL。我没有说过你必须与 JDBC 交互。我指的是它被翻译成什么。如前所述,在查询中使用参数;根据 JDO 规范,DN 文档
    • 我想我感到困惑的是,它现在看起来像是一个非常容易泄漏的抽象。 Postgres 失败了,因为我在我的代码中使用了一个文字层,甚至不需要知道 Postgres 正在被使用。我想我已经找到了如何参数化查询的方法,因此感谢您为我指明相关方向。但是我仍然无法找到有关此内容的文档。看到您似乎是“DataNucleus 人”,我想您也许可以将我引向“JDO 规范、DN 文档”以外的其他内容。
    猜你喜欢
    • 2020-12-13
    • 1970-01-01
    • 2015-05-19
    • 2015-09-21
    • 2011-11-09
    • 2017-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多