2
    EntityManager em = getEntityManager();

    EntityTransaction etx = em.getTransaction();
    etx.begin();

    Query query = em.createNamedQuery("login_procedure").setParameter("param1","user").setParameter("param2", "pw");


    Integer result = 23;
    try {
        System.out.println("query = " + query.getSingleResult());
    } catch (Exception e) {
        result = null;
        e.printStackTrace();
    }

    etx.commit();
    em.close();

...执行此代码我得到

[EL 警告]:2011-02-10 17:32:16.846--UnitOfWork(1267140342)--异常 [EclipseLink-4002] (Eclipse Persistence Services - 1.2.0.v20091016-r5565): org.eclipse.persistence.exceptions .DatabaseException 内部异常:org.firebirdsql.jdbc.FBSQLException:GDS 异常。335544569. 动态 SQL 错误 SQL 错误代码 = -104 令牌未知 - 第 1 行,第 36 列 = 错误代码:335544569 调用:EXECUTE PROCEDURE LOGIN_PROCEDURE(USER_NAME = ?, USER_PASSWORD = ?) bind => [user, pw] 查询:DataReadQuery(名称=“登录程序”)

-104 SQL 错误通常表示 SQL 语法错误。

在调用 query.getSingleResult() 之前,所有内容都会被正确处理。调用 query.getResultList() 不会改变任何东西。我已经尝试了几个 1.x 和 2.x EclipseLink 版本。Firebird DB 版本是 2.1。

JPA2 声明是:

    @Entity
@NamedStoredProcedureQuery(
        name = "login_procedure",
        resultClass = void.class,
        procedureName = "LOGIN_PROCEDURE",
        returnsResultSet = false,
        parameters = {
                @StoredProcedureParameter(queryParameter = "param1", name = "USER_NAME", direction = Direction.IN, type = String.class),
                @StoredProcedureParameter(queryParameter = "param2", name = "USER_PASSWORD", direction = Direction.IN, type = String.class)
        }
)
@Table(name = "USERS")
public class Login implements Serializable {
    @Id
    private Long id;
}

更新:在稍微修改之后,我相信 EclipseLink 实现中可能存在错误,因为EXECUTE PROCEDURE LOGIN_PROCEDURE(USER_NAME = ?, USER_PASSWORD = ?)不是用于调用过程的有效 Firebird 2.1 语法。

4

2 回答 2

1

通过指定 name="USER_NAME" 您正在使 Eclipselink 使用 'USER_NAME=?' 语法而不是仅仅传入未命名的参数。尝试删除名称定义。

于 2011-02-15T15:25:36.977 回答
0

这篇文章的启发,我找到了一个解决方案/解决方法:

public class JPATest {
final Session session;

JPATest() {
    final String DATABASE_USERNAME = "SYSDBA";
    final String DATABASE_PASSWORD = "masterkey";
    final String DATABASE_URL = "jdbc:firebirdsql:dbServer/3050:e:/my/db.fdb";
    final String DATABASE_DRIVER = "org.firebirdsql.jdbc.FBDriver";

    final DatabaseLogin login = new DatabaseLogin();
    login.setUserName(DATABASE_USERNAME);
    login.setPassword(DATABASE_PASSWORD);
    login.setConnectionString(DATABASE_URL);
    login.setDriverClassName(DATABASE_DRIVER);
    login.setDatasourcePlatform(new FirebirdPlatform());
    login.bindAllParameters();

    final Project project = new Project(login);
    session = project.createDatabaseSession();
    session.setLogLevel(SessionLog.FINE);
    ((DatabaseSession) session).login();

}

public static void main(String[] args) {
    final JPATest jpaTest = new JPATest();
    jpaTest.run();
}

protected void run() {
    testProcCursor();
}

/*
* Run Proc with scalar input and cursor output
*/
@SuppressWarnings("unchecked")
private void testProcCursor() {
    final StoredProcedureCall call = new StoredProcedureCall();
    call.setProcedureName("LOGIN");
    call.addUnamedArgument("USER_NAME"); // .addNamedArgument doesn't work
    call.addUnamedArgument("USER_PASSWORD");

    final DataReadQuery query = new DataReadQuery();
    query.setCall(call);
    query.addArgument("USER_NAME");
    query.addArgument("USER_PASSWORD");

    final List<String> queryArgs = new ArrayList<String>();
    queryArgs.add("onlinetester");
    queryArgs.add("test");

    final List outList = (List) session.executeQuery(query, queryArgs);
    final ListIterator<DatabaseRecord> listIterator = ((List<DatabaseRecord>) outList).listIterator();
    while (listIterator.hasNext()) {
        final DatabaseRecord databaseRecord = listIterator.next();
        System.out.println("Value -->" + databaseRecord.getValues());
    }
}

}

在我的特定配置中显然不支持命名参数,但在注释中使用未命名参数也没有解决问题。但是,如上所述,使用未命名的参数为我解决了这个问题。

于 2011-02-16T16:23:14.493 回答