Выполнение хранимых процедур в Firebird с использованием JPA NamedStoredProcedureQuery - PullRequest
2 голосов
/ 10 февраля 2011
    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 Warning]: 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")

Ошибка SQL -104 обычно указывает на ошибку синтаксиса SQL.

Все обрабатывается без ошибок, пока не будет вызван query.getSingleResult (). Вызов query.getResultList () ничего не меняет. Я пробовал несколько версий 1.x и 2.x EclipseLink. Версия БД Firebird - 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;
}

UPDATE: Поработав еще немного, я полагаю, что в реализации EclipseLink может возникнуть ошибка: EXECUTE PROCEDURE LOGIN_PROCEDURE (USER_NAME =?, USER_PASSWORD =?) недопустим синтаксис Firebird 2.1 для вызова процедур.

Ответы [ 2 ]

1 голос
/ 15 февраля 2011

Указав имя = "USER_NAME", вы заставляете Eclipselink использовать 'USER_NAME =?'синтаксис вместо просто передачи безымянного параметра.Попробуйте удалить определение имени.

0 голосов
/ 16 февраля 2011

Вдохновленный этим постом , я нашел решение / обходной путь:

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

}

Очевидно, что названные параметры не поддерживаются в моей конкретной конфигурации, но использование неназванных параметров в аннотациях также не решило проблему. Однако использование неназванных параметров, как указано выше, решило проблему для меня.

...