有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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) 个答案

  1. # 1 楼答案

    请提供使用DB游标的JPA/Hibernate代码。我认为您应该在Java代码中调用close()方法(可能在org.hibernate.ScrollableResults)来关闭游标对象