Соединение не закрывается - PullRequest
0 голосов
/ 24 апреля 2020

Я использую веб-сервис SpringBoot 2.0, используя Java 8. Мне пришлось использовать PreparedStatement для обработки сгустков, поэтому вместо того, чтобы позволить Spring создать соединение Oracle, мне пришлось создать свое собственное. Однако теперь у меня, кажется, есть утечка соединения, хотя я закрываю соединение после того, как я закончу, и после того, как я запустил свой webService 3 раза (я пропускаю 3 соединения каждый раз), я получаю ошибку:

 org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30002ms.
DEBUG - HikariPool-1 - Pool stats (total=10, active=9, idle=1, waiting=0)

Поэтому я добавил следующее в application.properties, чтобы найти утечку:

spring.datasource.hikari.leakDetectionThreshold=2000

, а затем я получил следующую ошибку при первом запуске моего веб-сервиса:

java.lang.Exception: Apparent connection leak detected
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128)
at com.clarivate.singularity.chemworkbench.dcrws.database.ReadFromDb.readStructureSearch(ReadFromDb.java:187)

Ниже приведен метод выдачи ошибки:

public class myClass(){
@Autowired
 NamedParameterJdbcTemplate  jdbcTemplate;  

@Transactional
public List<DcrData> readStructureSearch(String sqlStr,  String fileData) throws SQLException  {
    List<DcrData> dcrDataList = null;
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
try {
    conn =  this.jdbcTemplate.getJdbcTemplate().getDataSource().getConnection().unwrap(OracleConnection.class); // <<<< This is line 187 mentioned above which is giving the error
    Clob myClob =  conn.createClob();

    int ret = myClob.setString( 1, fileData);

    ps = conn.prepareStatement(sqlStr);
    ps.setClob(1,myClob);       // This works, Types.CLOB doesn't work.

    rs = ps.executeQuery();

    ResultSetHandler<List<DcrData>> handler = 
            new BeanListHandler<DcrData>(DcrData.class, new BasicRowProcessor(new GenerousBeanProcessor()));

    dcrDataList = handler.handle(rs);
    return  dcrDataList;
}finally {
    if (rs != null) {
        rs.close();
    }
    if (ps != null) {
        ps.close();
    }
    if (conn != null) {
        conn.close();
    }
    logger.info("DSxxx4");
}
}

Как создать соединение без утечек и почему Hikari считает, что мой метод conn.close () не закрывает соединение? Любые идеи приветствуются.

1 Ответ

1 голос
/ 25 апреля 2020

Я немного озадачен тем, что делает функция. Похоже, что выполняется ограничение select на CLOB, но я могу ошибаться. У меня были проблемы с воссозданием проблемы, не зная об этом.

Тем не менее, вот несколько вещей, которые нужно попробовать. Во-первых, вам не нужен NamedParameterJdbcTemplate, просто источник данных. Попробуйте вместо этого выполнить автоматическую разводку. Во-вторых, кажется, нет причины получать само сырое Oracle соединение, и вы можете напрямую использовать соединение, возвращаемое источником данных. В-третьих, шаблон try with resources облегчает выполнение кода Java автоматически обрабатывает закрытие ресурсов. Он доступен в Java 8. Наконец, возможно, освобождение CLOB поможет.

Вот пример с вещами, которые я упоминаю:

public class MyClass {

    @Autowired
    DataSource dataSource;

    @Transactional
    public List<DcrData> readStructureSearch(String sqlStr, String fileData) throws SQLException {

        try (Connection conn = this.dataSource.getConnection()) {
            Clob myClob = conn.createClob();

            myClob.setString(1, fileData);

            try (PreparedStatement ps = conn.prepareStatement(sqlStr)) {
                ps.setClob(1, myClob);

                try (ResultSet rs = ps.executeQuery()) {
                    ResultSetHandler<List<DcrData>> handler =
                            new BeanListHandler<>(DcrData.class, new BasicRowProcessor(new GenerousBeanProcessor()));

                    List<DcrData> dcrDataList = handler.handle(rs);

                    myClob.free();

                    return dcrDataList;
                }
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...