Stored procedures 使用JPA namedStoredProcess在Firebird中执行存储过程

Stored procedures 使用JPA namedStoredProcess在Firebird中执行存储过程,stored-procedures,jpa,firebird,eclipselink,firebird2.1,Stored Procedures,Jpa,Firebird,Eclipselink,Firebird2.1,…执行我得到的代码 [EL警告]:2011-02-10 17:32:16.846——工作单元(1267140342)——异常 [EclipseLink-4002](日食) 持久性服务- 1.2.0.v20091016-r5565):org.eclipse.persistence.exceptions.DatabaseException 内部异常: org.firebirdsql.jdbc.FBSQLException: GDS例外。335544569动态结构化查询语言 错误SQL错误代码=-10

…执行我得到的代码

[EL警告]:2011-02-10 17:32:16.846——工作单元(1267140342)——异常 [EclipseLink-4002](日食) 持久性服务- 1.2.0.v20091016-r5565):org.eclipse.persistence.exceptions.DatabaseException 内部异常: org.firebirdsql.jdbc.FBSQLException: GDS例外。335544569动态结构化查询语言 错误SQL错误代码=-104令牌 未知-第1行第36列 =错误代码:335544569调用:执行过程登录\u过程(用户名= ?,用户\密码=?)绑定=>[用户, pw]查询: DataReadQuery(name=“登录\程序”)

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

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

JPA2声明是:

    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();
更新: 经过进一步修改,我相信EclipseLink实现中可能会出现错误,因为执行过程登录过程(USER\u NAME=?,USER\u PASSWORD=?)不是调用过程的有效Firebird 2.1语法。

通过指定NAME=“USER\u NAME”您正在使Eclipselink使用“USER_NAME=?”语法,而不是只传递未命名的参数。尝试删除名称定义。

受此启发,我找到了一个解决方案/解决方法:

    @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;
}
公共类JPATest{
最后一届会议;
JPATest(){
最终字符串数据库\u USERNAME=“SYSDBA”;
最终字符串数据库\u PASSWORD=“masterkey”;
最终字符串DATABASE_URL=“jdbc:firebirdsql:dbServer/3050:e:/my/db.fdb”;
最终字符串数据库_DRIVER=“org.firebirdsql.jdbc.FBDriver”;
final DatabaseLogin login=新建DatabaseLogin();
login.setUserName(数据库\用户名);
login.setPassword(数据库密码);
setConnectionString(数据库的URL);
login.setDriverClassName(数据库驱动程序);
login.setDatasourcePlatform(新FirebirdPlatform());
login.bindAllParameters();
最终项目=新项目(登录);
session=project.createDatabaseSession();
session.setLogLevel(SessionLog.FINE);
((DatabaseSession)会话).login();
}
公共静态void main(字符串[]args){
最终JPATest JPATest=新JPATest();
jpaTest.run();
}
受保护的无效运行(){
testProcCursor();
}
/*
*使用标量输入和光标输出运行Proc
*/
@抑制警告(“未选中”)
私有void testProcCursor(){
最终StoredProcedureCall调用=新建StoredProcedureCall();
call.setProcedureName(“登录”);
call.addUnamedArgument(“用户名”);/。addNamedArgument不起作用
call.addUnamedArgument(“用户密码”);
final DataReadQuery query=新建DataReadQuery();
query.setCall(call);
query.addArgument(“用户名”);
query.addArgument(“用户密码”);
最终列表queryArgs=new ArrayList();
添加(“onlinetester”);
添加(“测试”);
最终列表大纲=(列表)会话.executeQuery(查询,查询);
最终ListIterator ListIterator=((列表)outList).ListIterator();
while(listIterator.hasNext()){
final DatabaseRecord DatabaseRecord=listIterator.next();
System.out.println(“Value-->”+databaseRecord.getValues());
}
}
}

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

get:“Call:executeprocedure LOGIN1(param1=?)”但错误保持不变。实际上,包含的括号不是有效的FBSQL语法。有效的FB SQL语法应该类似于“执行过程LOGIN1?”
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());
    }
}