본문 바로가기
개발 및 운영/Spring

sqlite-jdbc inmemory could not prepare statement 오류

by Joseph.Lee 2021. 10. 19.

sqlite jdbc driver 랑 Spring-boot 를 같이 사용하면서, inmemory database를 사용할 때 DDL-Auto를 통해 자동으로 테이블을 생성하게 하였지만 쿼리를 날리면

 

Caused by: org.hibernate.exception.GenericJDBCException: could not prepare statement

Caused by: org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (no such table: ...)

 

이런 오류가 발생하는 문제가 있었다.

 

https://www.baeldung.com/spring-boot-sqlite 에도 별 설정 없이 jdbc url 을 memory 로 주면 된다고 하는데 동작하지 않았다..

(다른 점은 jdbc driver 를 기본 sqlite 대신 https://github.com/Willena/sqlite-jdbc-crypt 를 사용했다는 것?)

 

한참 삽질했는데...ㅠㅠ 이유는 https://www.sqlite.org/sharedcache.html 에 있었다.

 

Enabling shared-cache for an in-memory database allows two or more database connections in the same process to have access to the same in-memory database. An in-memory database in shared cache is automatically deleted and memory is reclaimed when the last connection to that database closes.

 

당연한 이야기 일 수는 있지만.. shared cache inmemory db 는 해당 데이터베이스의 마지막 Connection 이 닫힐 때 자동으로 없어진다.

아마도 Spring-boot 에서 기본적으로 HikariCP를 써서 대부분의 경우에는 문제가 없었던거 같다. 하지만 난 이걸 쓰지 않았다...

암튼 DDL 할 당시랑 Select 할 당시에 Connection 이 끊겨서 (connection 개수가 0개가 되어서) DB가 지워진 것이었다.

 

암튼.. 아래 방식으로 해결했다.

혹은 hikariCP 를 사용하면서 minimum-idle 을 1 이상 주면 해결될 것이다.

    // An in-memory database in shared cache is automatically deleted and memory is reclaimed when the last connection to that database closes.
    private final AtomicReference<Connection> memoryConnection = new AtomicReference<>();
    
    @Bean
    public SQLiteDataSource dataSource() throws SQLException {
        SQLiteDataSource dataSource = new SQLiteDataSource();
        dataSource.setUrl("jdbc:sqlite:file:memdb1?mode=memory&cache=shared");
        this.memoryConnection.set(dataSource.getConnection());
        return dataSource;
    }
    
    @PreDestroy
    protected void cleanup() throws SQLException {
        Connection connection = memoryConnection.getAndSet(null);
        if (connection != null) {
            connection.close();
        }
    }

 

 

반응형

댓글