java – 停止Tomcat不会删除Derby db.lck
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java – 停止Tomcat不会删除Derby db.lck,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含11301字,纯文字阅读大概需要17分钟。
内容图文
![java – 停止Tomcat不会删除Derby db.lck](/upload/InfoBanner/zyjiaocheng/753/57db69b5288a4133bc917590e9a455ad.jpg)
(编辑:我已经在问题中添加了一笔赏金.我找到了一个解决方法(在下面发布了一个答案),但我希望有人能够解释为什么首先需要解决方法.)
我有一个Spring webapp,它在开发过程中连接到Derby数据库.这在第一次运行webapp时工作正常,但在后续运行中,它在启动时失败,“Derby的另一个实例可能已经启动了数据库”SQLException.
我知道这是因为当我关闭Tomcat时,与Derby的连接没有被关闭,即使我希望Spring自动处理它.所以我的问题是,如何正确断开与Derby的连接?不仅在手动停止Tomcat期间,而且在热部署新的.war文件期间?
我想避免使用Derby服务器,我也使用注释而不是XML配置.这是我原来的PersistConfig类:
package com.example.spring.config;
import java.beans.PropertyVetoException;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.derby.jdbc.EmbeddedDataSource;
import org.hibernate.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.jdbc.datasource.embedded.ConnectionProperties;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseConfigurer;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.orm.hibernate4.HibernateExceptionTranslator;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@ComponentScan({"com.example.spring.dao.jpa"})
@EnableTransactionManagement // <-- enable @Transactional annotations for spring @Component and stereotypes
public class PersistConfig{
@Bean
public HibernateExceptionTranslator exceptionTranslator() {
return new HibernateExceptionTranslator();
}
@Bean
public LocalSessionFactoryBean localSessionFactoryBean(DataSource dataSource, JpaVendorAdapter vendorAdapter) {
LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
localSessionFactoryBean.setDataSource(dataSource);
localSessionFactoryBean.setPackagesToScan("com.example.one", "com.example.two");
Properties properties = new Properties();
properties.putAll(vendorAdapter.getJpaPropertyMap());
localSessionFactoryBean.setHibernateProperties(properties);
return localSessionFactoryBean;
}
@Bean
public HibernateTransactionManager hibernateTransactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager(sessionFactory);
return hibernateTransactionManager;
}
@Configuration
public static class DevelopmentConfig{
@Bean
public DataSource dataSource() throws SQLException, PropertyVetoException {
DataSource dataSource = new SimpleDriverDataSource(new org.apache.derby.jdbc.EmbeddedDriver(), "jdbc:derby:C:\\Users\\Kevin\\Desktop\\DerbyDB", "", "");
System.out.println("RETURNING DATASOURCE");
return dataSource;
}
@Bean
JpaVendorAdapter vendorAdapter() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabase(Database.DERBY);
vendorAdapter.setDatabasePlatform("org.hibernate.dialect.DerbyDialect");
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setShowSql(true);
vendorAdapter.getJpaPropertyMap().put("hibernate.hbm2ddl.auto", "update");
vendorAdapter.getJpaPropertyMap().put("hbm2ddl.auto", "update");
return vendorAdapter;
}
}
}
我尝试使用Runtime.addShutdownHook()向整个JVM添加一个关闭钩子,我手动断开与Derby数据库的连接,但这似乎永远不会被解雇.
然后我被告知要查看EmbeddedDatabaseConfigurer接口以添加一个Spring关闭回调,我手动关闭数据库连接,这就是我提出的:
package com.example.spring.config;
import java.beans.PropertyVetoException;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.derby.jdbc.EmbeddedDataSource;
import org.hibernate.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.jdbc.datasource.embedded.ConnectionProperties;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseConfigurer;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.orm.hibernate4.HibernateExceptionTranslator;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@ComponentScan({"com.example.spring.dao.jpa"})
@EnableTransactionManagement // <-- enable @Transactional annotations for spring @Component and stereotypes
public class PersistConfig implements EmbeddedDatabaseConfigurer {
@Bean
public HibernateExceptionTranslator exceptionTranslator() {
return new HibernateExceptionTranslator();
}
@Bean
public LocalSessionFactoryBean localSessionFactoryBean(DataSource dataSource, JpaVendorAdapter vendorAdapter) {
LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
localSessionFactoryBean.setDataSource(dataSource);
localSessionFactoryBean.setPackagesToScan("com.example.one", "com.example.two");
Properties properties = new Properties();
properties.putAll(vendorAdapter.getJpaPropertyMap());
localSessionFactoryBean.setHibernateProperties(properties);
return localSessionFactoryBean;
}
@Bean
public HibernateTransactionManager hibernateTransactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager(sessionFactory);
return hibernateTransactionManager;
}
@Configuration
public static class DevelopmentConfig{
@Bean
public DataSource dataSource() throws SQLException, PropertyVetoException {
DataSource dataSource = new SimpleDriverDataSource(new org.apache.derby.jdbc.EmbeddedDriver(), "jdbc:derby:C:\\Users\\Kevin\\Desktop\\DerbyDB", "", "");
System.out.println("RETURNING DATASOURCE");
return dataSource;
}
@Bean
JpaVendorAdapter vendorAdapter() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabase(Database.DERBY);
vendorAdapter.setDatabasePlatform("org.hibernate.dialect.DerbyDialect");
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setShowSql(true);
vendorAdapter.getJpaPropertyMap().put("hibernate.hbm2ddl.auto", "update");
vendorAdapter.getJpaPropertyMap().put("hbm2ddl.auto", "update");
return vendorAdapter;
}
}
@Override
public void configureConnectionProperties(ConnectionProperties properties, String databaseName) {
System.out.println("CONFIGURE");
properties.setDriverClass(org.apache.derby.jdbc.EmbeddedDriver.class);
properties.setUrl("jdbc:derby:C:\\Users\\Kevin\\Desktop\\DerbyDB");
}
@Override
public void shutdown(DataSource ds, String databaseName) {
System.out.println("SHUTTING DOWN");
try {
DriverManager.getConnection("jdbc:derby:C:\\Users\\Kevin\\Desktop\\DerbyDB;shutdown=true");
}
catch (SQLException e) {
e.printStackTrace();
}
}
}
但是,似乎都没有调用configureConnectionProperties()函数和shutdown()函数.我显然不知道我在做什么,所以任何指针都非常感激.
解决方法:
编辑:添加重新启动嵌入式Derby数据库的精度和一个可能更简单的解决方案.
我可以至少部分地重现问题,理解它并修复它.但我不能说为什么BoneCP工作正常.我只是注意到,如果我在关闭tomcat并重新启动它之间等待足够多,那就可以了.我想BoneCP不会立即访问数据库,并等到第一次真正的连接.
首先是问题:当使用Derby作为嵌入式数据库时,数据库在第一次连接时启动,但必须明确地关闭它.如果不是,则不会删除db.lock文件,并且进一步的应用程序可能会在再次引导数据库时遇到问题.在tomcat中或者(默认情况下)在spring中没有任何东西可以自动关闭这样的数据库.
接下来,为什么使用EmbeddedDatabaseConfigurer的尝试不起作用:EmbeddedDatabaseConfigurer不是魔术标记,并且在类中继承它不足以让spring自动使用它.它只是一个必须由配置器实现的接口,以允许EmbeddedDatabaseFactory使用它.
最后解决了.您不应使用SimpleDriverDataSource从嵌入式Derby数据库获取连接,而应使用EmbeddedDatabaseFactory. Spring默认情况下知道Derby嵌入式数据库,你可以通过简单地设置类型来配置工厂……但是这只适用于内存数据库并且你有一个文件数据库!本来就太简单了……你必须向工厂注入一个配置器才能让一切正常.
现在代码(从你的第一个版本开始):
@Configuration
public static class DevelopmentConfig{
EmbeddedDatabaseFactory dsFactory;
public DevelopmentConfig() {
EmbeddedDatabaseConfigurer configurer = new EmbeddedDatabaseConfigurer() {
@Override
public void configureConnectionProperties(ConnectionProperties properties, String databaseName) {
System.out.println("CONFIGURE");
properties.setDriverClass(org.apache.derby.jdbc.EmbeddedDriver.class);
properties.setUrl("jdbc:derby:C:\\Users\\Kevin\\Desktop\\DerbyDB");
}
@Override
public void shutdown(DataSource dataSource, String databaseName) {
final String SHUTDOWN_CODE = "XJ015";
System.out.println("SHUTTING DOWN");
try {
DriverManager.getConnection("jdbc:derby:;shutdown=true");
} catch (SQLException e) {
// Derby 10.9.1.0 shutdown raises a SQLException with code "XJ015"
if (!SHUTDOWN_CODE.equals(e.getSQLState())) {
e.printStackTrace();;
}
}
}
};
dsFactory = new EmbeddedDatabaseFactory();
dsFactory.setDatabaseConfigurer(configurer);
}
@Bean
public DataSource dataSource() throws SQLException, PropertyVetoException {
System.out.println("RETURNING DATASOURCE");
return dsFactory.getDatabase();
}
// remaining of code unchanged
这样,我可以热重新加载战争,当tomcat关闭时,db.lock通常会被破坏.
编辑:
如果出现问题,Derby文档建议在关闭后添加以下命令以重新启动数据库:Class.forName(“org.apache.derby.jdbc.EmbeddedDriver”).newInstance(); .它可能是configureConnectionProperties方法的最后一条指令.
但实际上,解决方案可能更简单.真正需要添加到配置中的是正确关闭嵌入式驱动程序(最终重启).所以一个简单的PreDestroy(和eventualy` @ PostConstruct)注释方法就足够了:
@Configuration
public static class DevelopmentConfig{
@PreDestroy
public void shutdown() {
final String SHUTDOWN_CODE = "XJ015";
System.out.println("SHUTTING DOWN");
try {
DriverManager.getConnection("jdbc:derby:;shutdown=true");
} catch (SQLException e) {
// Derby 10.9.1.0 shutdown raises a SQLException with code "XJ015"
if (!SHUTDOWN_CODE.equals(e.getSQLState())) {
e.printStackTrace();
}
}
}
/* if needed ...
@PostConstruct
public void init() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
}
*/
@Bean
public DataSource dataSource() throws SQLException, PropertyVetoException {
DataSource dataSource = new SimpleDriverDataSource(new org.apache.derby.jdbc.EmbeddedDriver(), "jdbc:derby:C:\\Users\\Kevin\\Desktop\\DerbyDB", "", "");
System.out.println("RETURNING DATASOURCE");
return dataSource;
}
// remaining of code unchanged
此变体的主要兴趣在于您可以选择数据源,从SimpleDriverDataSource到实际池.
内容总结
以上是互联网集市为您收集整理的java – 停止Tomcat不会删除Derby db.lck全部内容,希望文章能够帮你解决java – 停止Tomcat不会删除Derby db.lck所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。