Data source is closed

原创
2016/06/01 10:45
阅读数 2.4K

今天想打一个可运行jar包,然后将配置文件jdbc.properties放在jar外加载。于是就用到了占位符。

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>hui</groupId>
	<artifactId>TestWithMaven</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>TestWithMaven</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.13</version>
		</dependency>
		<dependency>
			<groupId>org.apache.ibatis</groupId>
			<artifactId>ibatis-core</artifactId>
			<version>3.0</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.4.0</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.38</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-expression</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
		<dependency>
			<groupId>org.hamcrest</groupId>
			<artifactId>hamcrest-core</artifactId>
			<version>1.3</version>
		</dependency>

		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.3.1</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.4</version>
		</dependency>
		<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>1.2</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>4.2.21.Final</version>
		</dependency>
		<dependency>
			<groupId>org.javassist</groupId>
			<artifactId>javassist</artifactId>
			<version>3.18.1-GA</version>
		</dependency>
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.4</version>
		</dependency>

	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-shade-plugin</artifactId>
				<executions>
					<execution>
						<phase>package</phase>
						<goals>
							<goal>shade</goal>
						</goals>
						<configuration>
							<createDependencyReducedPom>false</createDependencyReducedPom>
							<transformers>
								<transformer
									implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
									<resource>META-INF/spring.handlers</resource>
								</transformer>
								<transformer
									implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
									<mainClass>socStatistics.StatisticsMain</mainClass>
								</transformer>
								<transformer
									implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
									<resource>META-INF/spring.schemas</resource>
								</transformer>

							</transformers>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>

beans.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:tx="http://www.springframework.org/schema/tx" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/aop   
	http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
	http://www.springframework.org/schema/tx   
	http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
        
	<context:annotation-config></context:annotation-config>
	<tx:annotation-driven transaction-manager="transactionManager"/>
    
	<bean id="statisticsDao" class="socStatistics.StatisticsDao">
	</bean>
	
	<!-- <context:property-placeholder location="classpath:jdbc.properties" />-->
	<context:property-placeholder location="file:../config/jdbc.properties" />
	
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
		<property name="driverClassName" value="${jdbc.driverClassName}"/>  
		<property name="url" value="${jdbc.url}"/>  
		<property name="username" value="${jdbc.username}"/>  
		<property name="password" value="${jdbc.password}"/>  
	</bean>
	
    
	 <!--
		<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> 
			 <property name="driverClassName" value="com.mysql.jdbc.Driver"/> 
			 <property name="url" value="jdbc:mysql://localhost:3306/statistics"/> 
			 <property name="username" value="root"/> 
			 <property name="password" value="java"/> 
		  </bean> 
		 -->
	<bean id="transactionManager"  
		class="org.springframework.orm.hibernate4.HibernateTransactionManager">  
		<property name="sessionFactory" ref="sessionFactory" />
	</bean> 
	
	<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">  
		<property name="dataSource" ref="dataSource" />  
		<property name="hibernateProperties">  
			<props>  
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>  
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>  
				<prop key="hibernate.format_sql">true</prop>  
			</props>  
		</property> 
        
		<property name="packagesToScan">  
			<list>  
				<value>socStatistics.entity</value>  
			</list>  
		</property>    
	</bean>  
	<!-- 配置JdbcTemplate -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
      
</beans>

jdbc.properties:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/statistics
jdbc.username=root
jdbc.password=java

其他代码略。

结果启动后报错:

[org.springframework.context.support.ClassPathXmlApplicationContext] -Closing org.springframework.context.support.ClassPathXmlApplicationContext@26f0a63f: startup date [Tue May 31 20:24:35 CST 2016]; root of context hierarchy
 Exception in thread "main" org.springframework.jdbc.CannotGetJdbcConnectionException : Could not get JDBC Connection; nested exception is java.sql.SQLException: Data source is closed
     at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80)
     at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:390)
     at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:470)
     at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:480)
     at socStatistics.StatisticsDao.getAll(StatisticsDao.java:47 )
     at socStatistics.Utils.getResult( Utils.java:118)
     at socStatistics.Utils.getResultMap( Utils.java:95)
     at socStatistics.Utils.getDayAndHour( Utils.java:59)
     at socStatistics.Utils.listStatisticResultDatas(Utils.java:27 )
     at socStatistics.StatisticsMain.main(StatisticsMain.java:37 )
Caused by: java.sql.SQLException: Data source is closed
     at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1362)
     at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
     at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
     at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
     ... 9 more

关键是不使用占位符,即如注释中直接将dataSource相关url/username等写死,则无异常。

通过异常信息at org.apache.commons.dbcp.BasicDataSource.createDataSource,即dbcp 产生dataSource时异常。于是将class="org.apache.commons.dbcp.BasicDataSource"改为class="org.springframework.jdbc.datasource.DriverManagerDataSource",如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:tx="http://www.springframework.org/schema/tx" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/aop   
	http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
	http://www.springframework.org/schema/tx   
	http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
        
	<context:annotation-config></context:annotation-config>
	<tx:annotation-driven transaction-manager="transactionManager"/>
    
	<bean id="statisticsDao" class="socStatistics.StatisticsDao">
	</bean>
	
	<!-- <context:property-placeholder location="classpath:jdbc.properties" />-->
	<context:property-placeholder location="file:../config/jdbc.properties" />
	
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close">  
		<property name="driverClassName" value="${jdbc.driverClassName}"/>  
		<property name="url" value="${jdbc.url}"/>  
		<property name="username" value="${jdbc.username}"/>  
		<property name="password" value="${jdbc.password}"/>  
	</bean>
	
    
	 <!--
		<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> 
			 <property name="driverClassName" value="com.mysql.jdbc.Driver"/> 
			 <property name="url" value="jdbc:mysql://localhost:3306/statistics"/> 
			 <property name="username" value="root"/> 
			 <property name="password" value="java"/> 
		  </bean> 
		 -->
	<bean id="transactionManager"  
		class="org.springframework.orm.hibernate4.HibernateTransactionManager">  
		<property name="sessionFactory" ref="sessionFactory" />
	</bean> 
	
	<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">  
		<property name="dataSource" ref="dataSource" />  
		<property name="hibernateProperties">  
			<props>  
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>  
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>  
				<prop key="hibernate.format_sql">true</prop>  
			</props>  
		</property> 
        
		<property name="packagesToScan">  
			<list>  
				<value>socStatistics.entity</value>  
			</list>  
		</property>    
	</bean>  
	<!-- 配置JdbcTemplate -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
      
</beans>

再运行,报错如下:

Caused by: org.springframework.beans.factory.BeanCreationException : Error creating bean with name 'jdbcTemplate' defined in class path resource [beans.xml]: Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException : Error creating bean with name 'dataSource' defined in class path resource [beans.xml]: Invalid destruction signature; nested exception is org.springframework.beans.factory.support.BeanDefinitionValidationException : Couldn't find a destroy method named 'close' on bean with name 'dataSource'
     at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
     at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1481)
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226)
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
     at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
     at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
     at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
     at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:512)
     at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:486)
     at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:615)
     at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:178)
     at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
     at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:308)
     ... 18 more
Caused by: org.springframework.beans.factory.BeanCreationException : Error creating bean with name 'dataSource' defined in class path resource [beans.xml]: Invalid destruction signature; nested exception is org.springframework.beans.factory.support.BeanDefinitionValidationException : Couldn't find a destroy method named 'close' on bean with name 'dataSource'
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:589)
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
     at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
     at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
     at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
     at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
     ... 33 more
Caused by: org.springframework.beans.factory.support.BeanDefinitionValidationException : Couldn't find a destroy method named 'close' on bean with name 'dataSource'
     at org.springframework.beans.factory.support.DisposableBeanAdapter.<init>(DisposableBeanAdapter.java:125)
     at org.springframework.beans.factory.support.AbstractBeanFactory.registerDisposableBeanIfNecessary(AbstractBeanFactory.java:1634)
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:586)
     ... 39 more

异常  信息比较明确:Couldn't find a destroy method named 'close' on bean with name 'dataSource',即对于DriverManagerDataSource,没有一个名为close的destroy 方法,于是将destroy-method="close"去掉,如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:tx="http://www.springframework.org/schema/tx" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/aop   
	http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
	http://www.springframework.org/schema/tx   
	http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
        
	<context:annotation-config></context:annotation-config>
	<tx:annotation-driven transaction-manager="transactionManager"/>
    
	<bean id="statisticsDao" class="socStatistics.StatisticsDao">
	</bean>
	
	<!-- <context:property-placeholder location="classpath:jdbc.properties" />-->
	<context:property-placeholder location="file:../config/jdbc.properties" />
	
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
		<property name="driverClassName" value="${jdbc.driverClassName}"/>  
		<property name="url" value="${jdbc.url}"/>  
		<property name="username" value="${jdbc.username}"/>  
		<property name="password" value="${jdbc.password}"/>  
	</bean>
	
    
	 <!--
		<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> 
			 <property name="driverClassName" value="com.mysql.jdbc.Driver"/> 
			 <property name="url" value="jdbc:mysql://localhost:3306/statistics"/> 
			 <property name="username" value="root"/> 
			 <property name="password" value="java"/> 
		  </bean> 
		 -->
	<bean id="transactionManager"  
		class="org.springframework.orm.hibernate4.HibernateTransactionManager">  
		<property name="sessionFactory" ref="sessionFactory" />
	</bean> 
	
	<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">  
		<property name="dataSource" ref="dataSource" />  
		<property name="hibernateProperties">  
			<props>  
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>  
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>  
				<prop key="hibernate.format_sql">true</prop>  
			</props>  
		</property> 
        
		<property name="packagesToScan">  
			<list>  
				<value>socStatistics.entity</value>  
			</list>  
		</property>    
	</bean>  
	<!-- 配置JdbcTemplate -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
      
</beans>

至此,成功。

注:要特别注意jdbc.properties里的每一个值的后面不要有空格,不然连接会被拒绝。

展开阅读全文
打赏
0
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
0
分享
返回顶部
顶部