一、Spring对持久层采用的策略
- 没有重新实现新的持久层,只是对现有持久层方案进行封装,更利于使用
- 采用DAO模式
- 提供了大量的模板类来简化编程(HibernateTemplate、JdbcTemplate等)
二、Spring对JDBC的支持
1、 配置数据源
方式一、开源数据库产品dbcp.BasicDataSource DBCP(database connection pool)
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/spring" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
或是新建文件jdbc.perperties,里面配置数据连接池
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>classpath:jdbc.properties</value>
</property>
</bean>
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<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>
其中jdbc.perperties中配置如下:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username = root
jdbc.password =root
方式二、采用Spring内置的数据源,Spring内置实现 DriverManagerDataSource
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/hibdb</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>windows</value>
</property>
</bean>
方式三、使用容器提供的数据源(如Tomcat,Weblogic,Sun Application Server)
用的少,这里不详细阐述,主要是使用JdbcTemplate或是HibernateTemplate模板类(封装了绝大多数数据库操作)
三、Spring 对DAO的支持
DAO模式优点
- 减少开发代码量 提高工作效率
- 降低系统资源消耗 提高系统性能
- 业务逻辑层与持久层(数据层)的分离,使数据与操作更为清晰。
- 数据访问独立到了一层,修改具体实现类,不影响系统的架构运行
DAO模式的四个组件
- DAO接口
- DAO接口实现类
- pojo值对象
- DAO实例的定位(工厂 或 spring注入)
1、使用Spring的Dao支持来写Dao层,继承JdbcDaoSupport类,JdbcDaoSupport类中有一个字段dataSource。也就是数据库连接,因此只需继承JdbcDaoSupport类,并给它注入dataSource,就隐式的获得了数据库连接,可以在bean.xml文件中注入connection(即:dataSource)
<beans>
<!-- spring 方式获得dataSource-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
<property name="url"><value>jdbc:mysql://localhost:3306/j2ee</value></property>
<property name="username"><value>root</value></property>
<property name="password"><value>123456</value></property>
</bean>
<bean id="xxx" class="包名.类名(dao的实现类)">
<property name="dataSource">
<ref local="dataSource"/>
</property>
</bean>
</beans>
2.在这个Dao 实现类中写一个内部类,使其实现:RowMapper接口,用来封装成具体的pojo对象,查询时用RowMapper实现类,代码如下:
private class PersonRowMapper implements RowMapper
{
public Object mapRow(ResultSet resultSet, int rowNumber)throws SQLException {
User user = new User();
user.setId(resultSet.getLong("id"));
user.setName(resultSet.getString("name"));
user.setSex(resultSet.getString("sex"));
user.setAge(resultSet.getInt("age"));
user.setAddr(resultSet.getString("addr"));
return user;
}
}
四、Spring对Hibernate的支持
1. 配置数据源,参考JDBC处
2. 配置sessionFactory
<!--sessionFactory-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.cdd.*" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">
true
</prop>
</props>
</property>
</bean>
3. 配置DAO
给DAO类注入SessionFactory
<bean id="UserDao" class="com.cdd.dao.impl.userDAOImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
五、Spring声明式的事务管理
1、概念:
Spring支持声明式事务。Spring的事务管理是通过spring AOP来实现的。
Spring使用事务服务代理和事务管理器(如HibernateTransactionManager)来支持事务服务。
Spring对事务的边界多了一种嵌套事务(PROPAGATION_NESTED)。
PROPAGATION_NESTED:如果客户端启动了事务T1,那么Bean启动一个嵌套在T1中的子事务T2;如果客户端没有启动事务,那么Bean会启动一个新的事务,类似于REQUIRED_NEW
2、Annotation形式来声明事务管理
(1)加入annotation.xsd以及txManager bean
(2)加上注解<tx:annotation-driven
<tx:annotation-driven transaction-manager="txManager"/>
(3)在需要事务的方法上加:@Transactional
注:
a)事务加在DAO层还是Service层?事务应该添加在事务(一组操作数据库的动作集合)开始和结束的地方。在此案例中添加log日志,加到service层。代码在后面。
b)使用SessionFactory.getCurrentSession 不要使用OpenSession
//DAO具体实现层的方法,可以直接从sessionFactory中拿出session
public void save(Log log) {
//整合Hibernate
Session session = sessionFactory.getCurrentSession();
session.save(log);
System.out.println(" log save!");
}
@Transactional详解
1.什么时候rollback回滚,只要事务其中的一部分或多步执行失败,导致没有步骤被提交,则事务必须回滚到最初的系统状态。
2.运行期异常,非运行期异常不会触发rollback
3.必须uncheck (没有catch)
4.不管什么异常,只要你catch了,spring就会放弃管理
5.事务传播特性:propagation_required
代码示例如下:
//添加用户
//事务边界,保存用户同时保存日志。
@Transactional(propagation = Propagation.REQUIRED)
//重要记住(默认):(propagation = Propagation.REQUIRED)在当前方法中,如果已有一个transaction,就加进去,如果没有transaction就会创建一个新的
//nested(内嵌)(用的很少)在当前存在的事务上新建事务,回滚的时候回滚到起始点
//never:不可以有事务
//required_new:如果当前有transaction则挂起当前的,新建一个。当回滚的时候不会带动新的事务回滚
//@Transaction properties
//readOnly:true。Connection is readOnly.只读无法执行插入和更新语句
public void add(User user){
Log log = new Log();
log.setMsg("hello hibernate");
logDAO.save(log);
userDAO.save(user);
}
(4)异常处理:
在默认情况下,Spring的容器对于非受查异常(服务模块中抛出的非受查异常),会回滚事务。对于受查异常,会提交事务。
如果即使发生了某种受查异常,也要回滚事务,可以用 “- 异常类型“来声明。同样,对于非受查异常,如果不要求回滚事务,可以用”+异常类型”来声明。
4、xml(推荐,可以同时配置好多方法)
Spring的事务管理其实就是AOP,Spring的事务管理是通过spring AOP来实现的。
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<aop:config>
<aop:pointcut expression="execution(public * com.cdd.service..*.*(..))" id="bussinessService" />
<aop:advisor pointcut-ref="bussinessService" advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="getUser" read-only="true" />
<tx:method name="add*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>