java - 带有嵌入式 H2 : Database may be already in use: "Locked by another process" 的 Tomcat WebApp

标签 java spring hibernate tomcat h2

我在嵌入式 H2 数据库上使用 Hibernate 开发 Maven Spring Boot Web 应用程序。 该应用程序使用 Maven 目标 tomcat7 部署在 Tomcat 8 应用程序容器上:从 Maven Tomcat 插件 (tomcat7-maven-plugin) 重新部署。

当我第一次尝试在 Tomcat 上部署这个 Web 应用程序时,我没有任何异常(在 Tomcat 重启后)。

但是当我尝试在 Tomcat 上重新部署此 Web 应用程序时,出现以下异常:

org.h2.jdbc.JdbcSQLException: Database may be already in use: "Locked by another process". Possible solutions: close all other connection(s); use the server mode; SQL statement: null/14cfb969fb93251ff134953c65dd1f05db2ecd34c6b [90020-145]

hibernate .cfg.xml

<?xml version='1.0' encoding='utf-8'?>

<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>

        <!-- Database connection settings -->
        <property name="connection.driver_class">org.h2.Driver</property>
        <property name="connection.url">jdbc:h2:file:d:/Profiles/mBaye/Developement/Run/spring-boot-web-seed-dev/db/springbootwebui;DB_CLOSE_DELAY=0;MVCC=TRUE</property>
        <property name="connection.username">sa</property>
        <property name="connection.password"/>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.H2Dialect</property>

        <!-- Disable the second-level cache  -->
        <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Drop and re-create the database schema on startup -->
        <!-- <property name="hbm2ddl.auto">create</property> -->
        <!-- Update the database schema on startup -->
        <property name="hbm2ddl.auto">update</property>

        <mapping resource="app/Greeting.hbm.xml"/>

    </session-factory>

</hibernate-configuration>

GreetingController.java

@Controller
public class GreetingController {

    private static Logger logger ;

    // A SessionFactory is set up once for an application
    private static final SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

    [...]

    private Greeting saveGreeting(Greeting greeting) {

        logger.info(new StringBuilder("greeting=").append(greeting.toString()).toString());

        Session session = null;
        Greeting ret = null;

        try {
            session = sessionFactory.openSession();
            session.beginTransaction();
            session.save( greeting );
            session.getTransaction().commit();
            // Return result
            ret = greeting ;
        } catch (Exception e) {
            logger.log(Level.SEVERE, new StringBuilder("Failed to save ").append(greeting.toString()).toString(), e);
        } finally {
            session.close();
        }

        if (ret != null) {
            logger.info(new StringBuilder("ret=").append(ret.toString()).toString());   
        } else {
            logger.info(new StringBuilder("ret=null").toString());
        }

        return ret ;
    }

    [...]
}

我在其他主题上读到,当 VM 正确退出时,数据库连接会自动关闭 (来源:What is the proper way to close H2?)

我想,当应用程序部署在 Tomcat 上时,数据库连接由 Tomcat 保持。

我想找到一种正确的方法来关闭 Tomcat 重新部署时的所有数据库连接。

提前致谢。

最佳答案

我终于找到了解决办法! :)

我将 H2 数据库连接 URL 的设置更改为:

<property name="connection.url">jdbc:h2:file:d:/Profiles/mBaye/Developement/Run/spring-boot-web-seed-dev/db/springbootwebui;MVCC=TRUE;DB_CLOSE_ON_EXIT=TRUE;FILE_LOCK=NO</property>

hibernate .cfg.xml

<?xml version='1.0' encoding='utf-8'?>

<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>

        <!-- Database connection settings -->
        <property name="connection.driver_class">org.h2.Driver</property>
        <property name="connection.url">jdbc:h2:file:d:/Profiles/mBaye/Developement/Run/spring-boot-web-seed-dev/db/springbootwebui;MVCC=TRUE;DB_CLOSE_ON_EXIT=TRUE;FILE_LOCK=NO</property>
        <property name="connection.username">sa</property>
        <property name="connection.password"/>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.H2Dialect</property>

        <!-- Disable the second-level cache  -->
        <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Drop and re-create the database schema on startup -->
        <!-- <property name="hbm2ddl.auto">create</property> -->
        <!-- Update the database schema on startup -->
        <property name="hbm2ddl.auto">update</property>

        <mapping resource="app/Greeting.hbm.xml"/>

    </session-factory>

</hibernate-configuration>

我不确定这是最好的解决方案,但它确实有效。

关于java - 带有嵌入式 H2 : Database may be already in use: "Locked by another process" 的 Tomcat WebApp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29915679/

相关文章:

java - 在 spring 中读取属性文件

java - 当依赖类存在多个 bean 时如何 Autowiring ?

java - 如果结果大小大于 1,则 Hibernate 返回重复值

java - 我可以在 TableView 中使用 CheckBoxTableCell 作为让用户选择多行的方法吗?

java并发实践14.6

Java 将用户重定向到 java 更新页面

java - hibernate : SetMaxResults not working with java. util.Map

java - 使用 Eclipse 将 JavaFX 项目导出到可运行的

java - 在 Spring SpEL 中转义 MongoDB 正则表达式字符 - 获取 SpelParseException

java - @Transactional (noRollbackFor=RuntimeException.class) 不会阻止在 RuntimeException 上回滚