java如何使用Hibernate自动释放游标?
我曾读到,hibernate 4.0直到4.1.3出现在关闭连接或执行语句后未释放/取消分配OracleSql游标(我不擅长数据库管理)的问题。
虽然我已经增加了数据库上的最大游标数,但再次达到最大游标数只是时间问题。我非常确定这就是问题所在,因为构建失败,而不是在运行特定测试或测试类时
这仍然是Hibernate 5中的已知问题吗?如果是,如何手动释放游标
为了完整性,我正在使用:
-Hibernate-core-5.0.11-据我所知,这应该能够处理
游标
-Hibernate-entitymanager-5.0.11
-Hibernate-jpa-2.1-api-1.0.0
-Oracle数据库11.2.0.1
(我想)导致问题的存储库:
package org.mypackage.status;
import java.util.stream.Stream;
import org.mypackage.entity.status.Status;
import org.mypackage.entity.status.StatusContract;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
public interface StatusContractRepository extends CrudRepository<StatusContract, Long>{
@Query("select cs from StatusContract cs")
Stream<StatusContract> streamAll();
@Query("select cs from StatusContract cs where cs.name=?1")
StatusContract findOneByName(final Status name);
}
我正在测试的服务功能,它使用前面提到的存储库:
@Service
public class StatusService {
private final StatusContractRepository statusContractRepository;
private final ContractRepository contractRepository;
public StatusService(final StatusContractRepository statusContractRepository, final ContractRepository contractRepository) {
this.statusContractRepository = Objects.requireNonNull(statusContractRepository, "statusContractRepository must not be null.");
this.contractRepository = Objects.requireNonNull(contractRepository, "contractRepository must not be null.");
}
public String setContractStatus(final DocComm lastDocComm) {
Contract contract = lastDocComm.getContract();
if (lastDocComm.getAnswer() != null) {
switch (lastDocComm.getAnswer().getDocumentType().getCode()) {
case DocumentType.A_REQ_CLARIFY:
contract.setStatus(statusContractRepository.findOneByName(Status.CLAR_RECEIVED));
break;
case DocumentType.A_REQ_DOC_ADDITIONAL:
contract.setStatus(statusContractRepository.findOneByName(Status.CLAR_RECEIVED));
break;
// there are more cases; they have the same behavior
default:
break;
}
} else if (lastDocComm.getRequest() != null) {
switch (lastDocComm.getRequest().getDocumentType().getCode()) {
case DocumentType.REQ_TERMS:
contract.setStatus(statusContractRepository.findOneByName(Status.REQ_TERM));
break;
case DocumentType.REQ_MODIFY:
contract.setStatus(statusContractRepository.findOneByName(Status.REQ_MODIFY));
break;
// there are more cases; they have the same behavior
// the first few calls are alright, or when I run specifically one call
// the problem occurs at build when it calls all the functions
default:
break;
}
}
contractRepository.save(contract);
return contract.getStatus().getFullName();
}
}
来自NetBeans的日志:
testChangeStatus_1
[WARN ] 2017-04-18 09:07:13 [o.h.e.j.s.SqlExceptionHelper:127]- SQL Error: 604, SQLState: 60000
2017-04-18 09:07:13 [o.h.e.j.s.SqlExceptionHelper:129]- ORA-00604: error occurred at recursive SQL level 1
ORA-01000: maximum open cursors exceeded
ORA-01000: maximum open cursors exceeded
[INFO ] 2017-04-18 09:07:13 [o.h.e.i.DefaultLoadEventListener:129]- HHH000327: Error performing load command : org.hibernate.exception.GenericJDBCException: could not extract ResultSet
[INFO ] 2017-04-18 09:07:13 [o.h.e.i.DefaultLoadEventListener:129]- HHH000327: Error performing load command : org.hibernate.exception.GenericJDBCException: could not extract ResultSet
[INFO ] 2017-04-18 09:07:13 [o.h.e.i.DefaultLoadEventListener:129]- HHH000327: Error performing load command : org.hibernate.exception.GenericJDBCException: could not extract ResultSet
[INFO ] 2017-04-18 09:07:14 [o.m.a.AbstractEntityListener:63]- DECLARE return_code number; BEGIN SP_STERGE_INREGISTRARE ('COMMUNICATION_DOC',6515, 'null', to_date('2017-04-18','YYYY-mm-dd'), 'FO', return_code); END;
[INFO ] 2017-04-18 09:07:14 [o.m.a.AbstractEntityListener:67]- SQL_CALL_RESULT: 1
[INFO ] 2017-04-18 09:07:14 [o.m.a.AbstractEntityListener:63]- DECLARE return_code number; BEGIN SP_STERGE_INREGISTRARE ('CONTRACT',9824, 'null', to_date('2017-04-18','YYYY-mm-dd'), 'FO', return_code); END;
[INFO ] 2017-04-18 09:07:14 [o.m.a.AbstractEntityListener:67]- SQL_CALL_RESULT: 1
[INFO ] 2017-04-18 09:07:14 [o.m.a.AbstractEntityListener:63]- DECLARE return_code number; BEGIN SP_STERGE_INREGISTRARE ('DOCUMENT',21551, 'null', to_date('2017-04-18','YYYY-mm-dd'), 'FO', return_code); END;
[INFO ] 2017-04-18 09:07:14 [o.m.a.AbstractEntityListener:67]- SQL_CALL_RESULT: 1
[INFO ] 2017-04-18 09:07:14 [o.m.a.AbstractEntityListener:63]- DECLARE return_code number; BEGIN SP_STERGE_INREGISTRARE ('DOCUMENT',21552, 'null', to_date('2017-04-18','YYYY-mm-dd'), 'FO', return_code); END;
[INFO ] 2017-04-18 09:07:14 [o.m.a.AbstractEntityListener:67]- SQL_CALL_RESULT: 1
testChangeStatus_2
[WARN ] 2017-04-18 09:07:14 [o.h.e.j.s.SqlExceptionHelper:127]- SQL Error: 604, SQLState: 60000
2017-04-18 09:07:14 [o.h.e.j.s.SqlExceptionHelper:129]- ORA-00604: error occurred at recursive SQL level 1
ORA-01000: maximum open cursors exceeded
ORA-01000: maximum open cursors exceeded
...
许多其他测试函数都是如此
如果需要进一步的细节,我会尽快提供
# 1 楼答案
请提供使用DB游标的JPA/Hibernate代码。我认为您应该在Java代码中调用
close()
方法(可能在org.hibernate.ScrollableResults
)来关闭游标对象