环境: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 sql查询数据库_hibernate

这样就可以在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模块

然后加入了模块之后,

spring sql查询数据库_spring_02

 

还需要添加@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">

这是现在完整的头

修改完毕之后,终于跑起来了。特此记录