五、Spring数据库操作
1.Spring+JDBC
(1)特点
静态代码+动态变量 = jdbc编程。在spring中动态变量可以用注入的形式给予,这样的编程方式适合包装成模版,
静态代码构成了模版,而动态变量则是需要传入的参数.
(2)引入DataSource
在spring中注入DataSource,一般采用c3p0
(3)核心类JdbcTemplate
* 它是基于模版的设置
* 完成了资源的创建和释放的工作
* 简化为我们对JDBC的操作
* 完成了对JDBC的核心流程的工作,包括SQL语句的创建和执行
* 仅需要传递DataSource就可以把它实例化
* JdbcTemplate只需要创建一次
* JdbcTemplate是线程安全类
(4)使用JdbcTemplate
在Dao类中,用JdbcTemplate作为属性,用spring对JdbcTemplate进行注入.
再对jdbcTemplate进行DataSource注入.
(5)继承JdbcDaoSupport
在Dao类中,继承JdbcDaoSupport,因为JdbcDaoSupport已经有了jdbcTemplate的引用,所以
只要继承jdbcDaoSupport就相当于有了jdbcTemplate属性.
(6)使用properties文件
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>jdbc.properties</value>
</list>
</property>
</bean>
或者
<context:property-placeholder location="classpath:jdbc.properties" />
jdbc.properties文件中配置连接信息
jdbc.driverclass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/databasename
jdbc.username=root
jdbc.password=root
c3p0.pool.size.max=10
c3p0.pool.size.min=2
c3p0.pool.size.ini=3
c3p0.pool.size.increment=2
(7)RowMapper的使用
* 由来: 在jdbc的操作中,有很多情况下是要将ResultSet里的数据封装到一个持久化Bean里,再把持久化
Bean封装到集合中,这样会造成大量的代码的重复,不利于代码重用.而RowMapper正好解决这个问题.
* 使用:
首先,写一个类实现RowMapper接口
public class AccountMapper implements RowMapper {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException{
Account account = new Account();
account.setAccountid(ts.getString("accountid"));
account.setBalance(rs.getDouble("balance"));
return account;
}
}
其次,在回调接口中,作为参数进行传入即可
this.getJdbcTemplate().query(sql,new AccountMapper());
(8)Spring的事务管理器
* spring事务管理器介绍
spring没有直接管理事务,而是将管理事务的责任委托给JTA或响应的持久性机制所提供的某个特定平台的事务实现
org.springframework.jdbc.datasource.DataSourceTransactionManager
在单一的JDBC Datasource中的管理事务
org.springframework.orm.hibernate3.HibernateTransactionManager
当持久化机制是hibernate时,用它来管理事务》
org.springframework.jdo.JdoTransactionManager
当持久化机制是Jdo时,用它来管理事务
org.springframework.transaction.jta.JtaTransactionManager
使用一个JTA实现来管理事务,在一个事务跨越多个资源时必须使用
org.springframework.orm.ojb.PersistenceBrokerTransactionManager
当apache的ojb用作持久化机制时,用它来管理事务.
(9)spring事务的配置
* 以注解方式配置(命名空间略)
注意:方法的事务设置将被优先执行.也就是说方法的事务声明优先于类级别的事务设置.
2.Hibernate+Hibernate
(1)xml文件形式
(2)注解形式
* 在配置文件中引入spring的自动扫描机制
<context:component-scan base-package="com.liu" />
* 在配置文件中引入注解解析器
<tx:annotation-driven transaction-manager="txManager"/>
* 在service层通过@Transaction进行注解
6.struts2+spring+hibernate整合
(1)添加需要的jar包
(2)配置web.xml
(3)OpenSessionInView
由于使用的是spring的声明式事务处理方式,所以在调用this.getHibernateTemplate().load方法时,
使用了hibernate的懒加载技术。当把一个实体Bean从数据库中加载完以后,只能加载其ID值。
这个时候spring的声明式事务处理方式已经把session给关闭掉了。所以当值在页面输出时会产生异常。
1.Spring+JDBC
(1)特点
静态代码+动态变量 = jdbc编程。在spring中动态变量可以用注入的形式给予,这样的编程方式适合包装成模版,
静态代码构成了模版,而动态变量则是需要传入的参数.
(2)引入DataSource
在spring中注入DataSource,一般采用c3p0
(3)核心类JdbcTemplate
* 它是基于模版的设置
* 完成了资源的创建和释放的工作
* 简化为我们对JDBC的操作
* 完成了对JDBC的核心流程的工作,包括SQL语句的创建和执行
* 仅需要传递DataSource就可以把它实例化
* JdbcTemplate只需要创建一次
* JdbcTemplate是线程安全类
(4)使用JdbcTemplate
在Dao类中,用JdbcTemplate作为属性,用spring对JdbcTemplate进行注入.
再对jdbcTemplate进行DataSource注入.
(5)继承JdbcDaoSupport
在Dao类中,继承JdbcDaoSupport,因为JdbcDaoSupport已经有了jdbcTemplate的引用,所以
只要继承jdbcDaoSupport就相当于有了jdbcTemplate属性.
(6)使用properties文件
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>jdbc.properties</value>
</list>
</property>
</bean>
或者
<context:property-placeholder location="classpath:jdbc.properties" />
jdbc.properties文件中配置连接信息
jdbc.driverclass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/databasename
jdbc.username=root
jdbc.password=root
c3p0.pool.size.max=10
c3p0.pool.size.min=2
c3p0.pool.size.ini=3
c3p0.pool.size.increment=2
(7)RowMapper的使用
* 由来: 在jdbc的操作中,有很多情况下是要将ResultSet里的数据封装到一个持久化Bean里,再把持久化
Bean封装到集合中,这样会造成大量的代码的重复,不利于代码重用.而RowMapper正好解决这个问题.
* 使用:
首先,写一个类实现RowMapper接口
public class AccountMapper implements RowMapper {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException{
Account account = new Account();
account.setAccountid(ts.getString("accountid"));
account.setBalance(rs.getDouble("balance"));
return account;
}
}
其次,在回调接口中,作为参数进行传入即可
this.getJdbcTemplate().query(sql,new AccountMapper());
(8)Spring的事务管理器
* spring事务管理器介绍
spring没有直接管理事务,而是将管理事务的责任委托给JTA或响应的持久性机制所提供的某个特定平台的事务实现
org.springframework.jdbc.datasource.DataSourceTransactionManager
在单一的JDBC Datasource中的管理事务
org.springframework.orm.hibernate3.HibernateTransactionManager
当持久化机制是hibernate时,用它来管理事务》
org.springframework.jdo.JdoTransactionManager
当持久化机制是Jdo时,用它来管理事务
org.springframework.transaction.jta.JtaTransactionManager
使用一个JTA实现来管理事务,在一个事务跨越多个资源时必须使用
org.springframework.orm.ojb.PersistenceBrokerTransactionManager
当apache的ojb用作持久化机制时,用它来管理事务.
(9)spring事务的配置
* 以xml配置的形式(***号表示需要引入的名称空间)
<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/tx
*** http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<!-- 配置c2p0数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db" />
<property name="user" value="root" />
<property name="password" value="root" />
<property name="maxPoolSize" value="10" />
<property name="minPoolSize" value="2" />
<property name="initialPoolSize" value="3" />
<property name="acquireIncrement" value="2" />
</bean>
<!-- 配置jdbc模版 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置jdbc的事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置通知,其中save开头的方法,配置了传播属性与隔离级别 -->
<tx:advice id="advice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 配置切入点 -->
<aop:config>
<aop:pointcut expression="execution(*com.liu.service..*.*(..))" id="accountservice"/>
<aop:advisor advice-ref="advice" pointcut-ref="accountservice"/>
</aop:config>
<!-- 配置dao层 -->
<bean id="accountDao" class="com.liu.dao.impl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<!-- 配置业务层 -->
<bean id="accountService" class="com.liu.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao" />
</bean>
</beans>
* 以注解方式配置(命名空间略)
<!-- 启动spring的自动扫描功能 -->
<context:component-scan base-package="com.liu"></context:component-scan>
<!-- 配置c2p0数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db" />
<property name="user" value="root" />
<property name="password" value="root" />
<property name="maxPoolSize" value="10" />
<property name="minPoolSize" value="2" />
<property name="initialPoolSize" value="3" />
<property name="acquireIncrement" value="2" />
</bean>
<!-- 配置jdbc模版 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置jdbc的事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 采用@Transactional注解方式使用事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
//Dao层代码
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {
@Resource(name="jdbcTemplate")
private JdbcTemplate jdbcTemplate;
//...
}
//service层代码
@Service("accountService")
@Transactional(readOnly=true)
public class AccountServiceImpl implements AccountService {
@Resource(name="accountDao")
private AccountDao accountDao;
@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT)
public void saveAccount(Account account) throws Exception {
//...
}
}
注意:方法的事务设置将被优先执行.也就是说方法的事务声明优先于类级别的事务设置.
2.Hibernate+Hibernate
(1)xml文件形式
<beans ...>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
<!-- 配置hibernate模版,利用SessionFactory获取session -->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<!-- 配置hibernate的事务管理器,切面 -->
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:advice id="advice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
<tx:method name="delete*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
<tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 配置切入点 -->
<aop:config>
<aop:pointcut expression="execution(* com.liu.service..*.*(..))" id="perform"/>
<!-- 将切入点应用到通知 -->
<aop:advisor advice-ref="advice" pointcut-ref="perform"/>
</aop:config>
</beans>
(2)注解形式
* 在配置文件中引入spring的自动扫描机制
<context:component-scan base-package="com.liu" />
* 在配置文件中引入注解解析器
<tx:annotation-driven transaction-manager="txManager"/>
* 在service层通过@Transaction进行注解
6.struts2+spring+hibernate整合
(1)添加需要的jar包
(2)配置web.xml
<!-- 监听器的形式整合spring -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext.xml</param-value>
</context-param>
<!-- 配置OpenSessionInViewFilter,解决懒加载引起的异常 -->
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<!-- 过滤器的形式整合struts2 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
(3)OpenSessionInView
由于使用的是spring的声明式事务处理方式,所以在调用this.getHibernateTemplate().load方法时,
使用了hibernate的懒加载技术。当把一个实体Bean从数据库中加载完以后,只能加载其ID值。
这个时候spring的声明式事务处理方式已经把session给关闭掉了。所以当值在页面输出时会产生异常。