使用休眠的当前会话执行存储过程后,无法执行任何读/写操作

时间:2019-07-05 10:06:48

标签: java sql-server hibernate stored-procedures callable-statement

在使用 Hibernate(版本5.4.2.final) getCurrentSession() <时,执行以下方法(包含 SQL Server过程)时,我看到了行为上的差异。 / p>

public List<A> notWorkingA() {
    Session session = sessionFactory.getCurrentSession();
    session.doWork(connection -> {
        try(CallableStatement callableStatement = connection.prepareCall("{ call PROCEDURE_WITH_NO_OUTPARAM() }")){
            callableStatement.execute();
        }
    });
    CriteriaBuilder builder = session.getCriteriaBuilder();
    CriteriaQuery<A> criteriaQuery = builder.createQuery(A.class);
    Root<A> rootObject = criteriaQuery.from(A.class);
    Predicate mainPredicate = builder.and(
            builder.equal(rootObject.get("p1"), 1),
            builder.equal( rootObject.get("p2"), "SOMEVALUE")
    );
    criteriaQuery.select(rootObject).where(mainPredicate);
    Query<A> query = session.createQuery(criteriaQuery);
    return query.getResultList();
}

public List<A> workingA() {
    Session session = sessionFactory.openSession();
    session.doWork(connection -> {
        try(CallableStatement callableStatement = connection.prepareCall("{ call PROCEDURE_WITH_NO_OUTPARAM() }")){
            callableStatement.execute();
        }
    });
    SessionFactoryUtils.closeSession(session);

    session = sessionFactory.getCurrentSession();
    CriteriaBuilder builder = session.getCriteriaBuilder();
    CriteriaQuery<A> criteriaQuery = builder.createQuery(A.class);
    Root<A> rootObject = criteriaQuery.from(A.class);
    Predicate mainPredicate = builder.and(
            builder.equal(rootObject.get("p1"), 1),
            builder.equal( rootObject.get("p2"), "SOMEVALUE")
    );
    criteriaQuery.select(rootObject).where(mainPredicate);
    Query<A> query = session.createQuery(criteriaQuery);
    return query.getResultList();
}

public List<A> notWorkingB() {
    Session session = sessionFactory.getCurrentSession();
    session.doWork(connection -> {
        try(CallableStatement callableStatement = connection.prepareCall("{ call PROCEDURE_WITH_OUTPARAM() }")){
            callableStatement.registerOutParameter(1, Types.VARCHAR);
            callableStatement.execute();
        }
    });
    CriteriaBuilder builder = session.getCriteriaBuilder();
    CriteriaQuery<A> criteriaQuery = builder.createQuery(A.class);
    Root<A> rootObject = criteriaQuery.from(A.class);
    Predicate mainPredicate = builder.and(
            builder.equal(rootObject.get("p1"), 1),
            builder.equal( rootObject.get("p2"), "SOMEVALUE")
    );
    criteriaQuery.select(rootObject).where(mainPredicate);
    Query<A> query = session.createQuery(criteriaQuery);
    return query.getResultList();
}

public List<A> workingB() {
    Session session = sessionFactory.getCurrentSession();
    session.doWork(connection -> {
        try(CallableStatement callableStatement = connection.prepareCall("{ call PROCEDURE_WITH_OUTPARAM() }")){
            callableStatement.registerOutParameter(1, Types.VARCHAR);
            callableStatement.execute();
            log.info(callableStatement.getString(1));
        }
    });
    CriteriaBuilder builder = session.getCriteriaBuilder();
    CriteriaQuery<A> criteriaQuery = builder.createQuery(A.class);
    Root<A> rootObject = criteriaQuery.from(A.class);
    Predicate mainPredicate = builder.and(
            builder.equal(rootObject.get("p1"), 1),
            builder.equal( rootObject.get("p2"), "SOMEVALUE")
    );
    criteriaQuery.select(rootObject).where(mainPredicate);
    Query<A> query = session.createQuery(criteriaQuery);
    return query.getResultList();
}

在执行notWorkingA()notWorkingB()的行query.getResultList()时出现以下错误

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The server failed to resume the transaction. Desc:6e00000008.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:217)
    at com.microsoft.sqlserver.jdbc.TDSTokenHandler.onEOF(tdsparser.java:251)
    at com.microsoft.sqlserver.jdbc.TDSParser.parse(tdsparser.java:81)
    at com.microsoft.sqlserver.jdbc.TDSParser.parse(tdsparser.java:36)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection$1ConnectionCommand.doExecute(SQLServerConnection.java:1835)
    at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:6276)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1794)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectionCommand(SQLServerConnection.java:1840)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.rollback(SQLServerConnection.java:2043)
    at com.mchange.v2.c3p0.impl.NewProxyConnection.rollback(NewProxyConnection.java:860)
    at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.rollback(AbstractLogicalConnectionImplementor.java:116)
    ... 49 more

经过一些调试后,我得到了notWorkingB()的修复程序,就像它像在callableStatement.getString(1)中那样调用workingB()一样可以工作(但不了解根本原因)。但是对于notWorkingA()来说,由于它是没有输出参数的过程,因此我无法在此处执行此解决方法,并且如果它像openSession()中那样使用workingA(),它将可以正常工作。

所以我想知道这个问题的根本原因是什么。另外,由于交易是在过滤器中进行管理的,因此我该如何使notWorkingA()currentSession()一起使用。

注意:
此案例在休眠3 中正常工作。仅在迁移到休眠5

之后,问题才会出现

0 个答案:

没有答案