环境:spring3 + hibernate3
对于数据库一些参数不需要经常修改,我们一般是写在配置文件,但是有时候又需要修改,spring提供了一个<content:property-placeholder>
元素
只需要在spring配置文件添加<context:property-placeholder location="classpath:jdbc.properties"/> 即可
或者
<bean id="propertyPlaceholderConfigurer" class="org.springframework,beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations">
<list>
<value>jdbc.properties<value/>
<如果有多个>
<value>jdbc.properties<value/>
</list>
</property>
</bean>
除了这种方式还可以使用另外一种方式:
<context:property-placeholder ignore-unresolvable="true" location="classpath:spring-orm-jdbc.properties" />
如果有多个可以用逗号分隔
<context:property-placeholderlocation="classpath:spring-orm-jdbc.properties,classpath:spring-orm-jdbc.properties" />
如果名字相同的,会取最后一个。
配置文件如下:
这样就可以在spring的bean配置的时候使用这些参数
下一步是先配置数据源,使用的是阿里巴巴的druid.pool,下面是配置内容:
<!-- 配置数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
<property name="driverClassName" value="${jdbc.driver}" />
<!-- 基本属性 url、user、password -->
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" /> <!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="${jdbc.pool.init}" />
<property name="minIdle" value="${jdbc.pool.minIdle}" />
<property name="maxActive" value="${jdbc.pool.maxActive}" /> <!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="60000" /> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" /> <property name="testWhileIdle" value="true" />
<!-- 这里建议配置为TRUE,防止取到的连接不可用 -->
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="false" /> <!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="true" />
<property name="maxPoolPreparedStatementPerConnectionSize"
value="20" /> <!-- 这里配置提交方式,默认就是TRUE,可以不用配置 -->
<property name="defaultAutoCommit" value="true" /> <!-- 验证连接有效与否的SQL,不同的数据配置不同 -->
<property name="validationQuery" value="${jdbc.testSql}" />
<property name="filters" value="stat" />
</bean>
因为整合spring和hibernate,sessionFactory的配置如下:
<!-- 配置SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <!-- 依赖数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- Hibernate框架相关配置 -->
<property name="hibernateProperties">
<props>
<!-- 指定连接的数据库类型方言 -->
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<!--显示SQL语句 输出到控制台-->
<prop key="hibernate.show_sql">true</prop>
<!--以格式良好的方式显示SQL语句-->
<prop key="hibernate.formate_sql">true</prop>
</props>
</property>
<!-- 自动扫描mapping -->
<property name="mappingDirectoryLocations">
<list>
<value>classpath*:/mappings/</value>
</list>
</property>
</bean>
在加载hibernate映射文件的时候踩了个坑,主要是mappingDirectoryLocations的配置问题,在网上查询得知:
mappingDirectoryLocations 是目录,
mappingLocations 是具体某个文件
mappingJarLocations 是jar包
但是我一开始是这样配置的:
<!-- 自动扫描mapping -->
<property name="mappingDirectoryLocations">
<list>
<value>classpath*:/mappings/**/*.hbm.xml</value>
</list>
</property>
结果测试的时候报下面错误:
Caused by: java.lang.IllegalArgumentException: Mapping directory location [file [D:\workspace\spring-orm\target\classes\mappings\hibernate\user.hbm.xml]] does not denote a directory
接下来是配置事务,
<!-- 配置spring事务 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
实现事务有2种形式:
方式1:基于aop
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="load*" read-only="true" />
<tx:method name="execute" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(* com.spring.orm.hibernate.*.*(..))" id="txPointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
方式2:基于注解
proxy-target-class 如果是true,需要导入cglib-nodep-2.1_3.jar包,因为我的版本是spring3 否则会报下面错误:
org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.
一开始是proxy-target-class=true, 但是有警告
WARN [org.springframework.aop.framework.Cglib2AopProxy] - Unable to proxy method [public final void org.springframework.orm.hibernate3.support.HibernateDaoSupport.setSessionFactory(org.hibernate.SessionFactory)] because it is final: All calls to this method via a proxy will be routed directly to the proxy.
CGLIB使用的是继承的方式,不能代理final的类或方法,后来改成了false 使用jdk的继承代理
配置完毕后,高高兴兴开始测试,用的是JUnit测试,结果一开始跑的时候,没反应,报错了,连配置文件都加载不进来,
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-context-jdbc.xml");
后来查询需要用到spring-test模块
然后加入了模块之后,
还需要添加@RunWith(SpringJUnit4ClassRunner.class) 注解
网上的说法是:
@RunWith:用于指定junit运行环境,是junit提供给其他框架测试环境接口扩展,为了便于使用spring的依赖注入,spring提供了org.springframework.test.context.junit4.SpringJUnit4ClassRunner作为Junit测试环境
@ContextConfiguration注解加载配置文件,因为我就一个,所以直接加载,如果有多个的话 写在applicationContext.xml里面,然后加载applicationContext.xml 即可
@Autowired //自动注入
private SessionFactory sessionFactory;
自动注入SessionFactory
途中遇到过2个问题:
错误1:
java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
缺少了commons-logging包
错误2:
cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element
The prefix "tx" for element "tx:annotation-driven" is not bound.
缺少了头文件
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
添加之后发现White spaces are required between publicId and systemId. 查询得知是顺序出错,
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
这是现在完整的头
修改完毕之后,终于跑起来了。特此记录