Я видел разницу в поведении при выполнении следующих методов (содержит Процедура SQL Server ) с Hibernate (версия 5.4.2.final) getCurrentSession()
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()
, так как транзакция управляется в Filter .
Примечание:
Этот случай работал правильно в Hibernate 3 . Проблема возникает только после перехода на Hibernate 5