使用JPA NamedStoredProcedureQuery在Firebird中执行存储过程

时间:2011-02-10 16:47:48

标签: stored-procedures jpa firebird eclipselink firebird2.1

    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     持久性服务 -     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 => [用户,     pw]查询:     DataReadQuery(name =“login_procedure”)

  

-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语法。 / p>

2 个答案:

答案 0 :(得分:1)

通过指定name =“USER_NAME”,您使用“USER_NAME =?”制作Eclipselink语法而不是仅传入未命名的参数。尝试删除名称定义。

答案 1 :(得分:0)

this post的启发,我找到了解决方案/解决方法:

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());
    }
}

}

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