要了解spring的数据操作,先了解事务
Spring中关于事务的三个重要接口:
TransactionDefinition(描述事务的各种属性的定义)
PlatfromTransactionManager(事务管理器)
TransactionStatus(一个事务具体运行状态)
几个重要概念:
事务隔离级别
要先了解脏读,不可重复读,幻读,第一类更新丢失,第二类更新丢失,
再了解各个级别,各个级别在TransactionDefinition有定义
static int | ISOLATION_DEFAULT |
static int | ISOLATION_READ_COMMITTED |
static int | ISOLATION_READ_UNCOMMITTED |
static int | ISOLATION_REPEATABLE_READ |
static int | ISOLATION_SERIALIZABLE |
事务传播特性:TransactionDefinition中定义了7种事务传播行为:
static int | PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。 |
static int | PROPAGATION_NESTED 如果一个活动的事务存在,则运行在一个嵌套的事务中.如果没有活动事务,则按TransactionDefinition.PROPAGATION_REQUIRED属性执行 |
static int | PROPAGATION_NEVER 总是非事务地执行,如果存在一个活动事务,则抛出异常 |
static int | PROPAGATION_NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务。 |
static int | PROPAGATION_REQUIRED 如果存在一个事务,则支持当前事务。如果没有事务则开启 |
static int | PROPAGATION_REQUIRES_NEW 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。 |
static int | PROPAGATION_SUPPORTS 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行 |
事务超时,在TransactionDefinition中定义了:
static int | TIMEOUT_DEFAULT |
如果设置了时间,超时后会回滚。
只读状态:指只读事务。
Spring为不同的持久化技术写了不同的事务管理器,它们都是PlatfromTransactionManager的子类:
AbstractPlatformTransactionManager, CciLocalTransactionManager, DataSourceTransactionManager, HibernateTransactionManager,
HibernateTransactionManager, JdoTransactionManager, JmsTransactionManager, JmsTransactionManager102, JpaTransactionManager,
JtaTransactionManager,OC4JJtaTransactionManager, WebLogicJtaTransactionManager, WebSphereUowTransactionManager
其中常用的DataSourceTransactionManager提供给jdbc或Ibatis等使用Connection的技术使用,HibernateTransactionManager提供给hibernate框架使用,上面有两个hibernateTransaction在不同的包下,用来支持不同的版本,一个是hibernate3一个是hibernate4。
Spring中使用JDBC
1.首先设置数据源到spring中
<beanid="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<propertyname="driverClassName"
value="${jdbc.driverClassName}"/>
<propertyname="url"value="${jdbc.url}"/>
<propertyname="username"value="${jdbc.username}"/>
<propertyname="password"value="${jdbc.password}"/>
</bean>
这里使用的是dbcp数据源,也可以选择使用c3p0,关于两者属性和配置方式,参考:http://wenku.baidu.com/view/6c57e71652d380eb62946d47.html
2.配置事务管理器
<beanid="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"/>
3.把事务管理的advice,织入到目标方法中
<tx:adviceid="jdbcAdvice"transaction-manager="transactionManager ">
<tx:attributes>
<tx:methodname="*"/>
</tx:attributes>
</tx:advice>
上面配置了一个增强,用来给目标方法前后插入事务代码,下面把增强织入到目标方法中
<aop:configproxy-target-class="true">
<aop:pointcutid="serviceJdbcMethod"
expression="execution(public*auscend.service.*.*(..))"/>
<aop:advisorpointcut-ref="serviceJdbcMethod"advice-ref="hiberAdvice"/>
</aop:config>
4.由于在dao层要操作数据库,spring为jdbc提供了一个JdbcTemplate,可以通过这个类的api对数据库操作
<beanid="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource"/>
也可以使用
<beanid="simpleJdbcTemplate"
class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-argref="dataSource"/>
</bean>
NamedParameterJdbcTemplate可以在sql语句不使用?做占位符,而使用:name :age这样的方式
5.把jdbcTemplate注入到Dao中使用即可,具体jdbcTemplate的方法参看api
Spring中使用Hibernate,与jdbc一致
1.配置数据源,同上
2.配置sessionFactory
<beanid="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:dataSource-ref="dataSource"> <!--如果不想一个类一个类的写可以使用p:packagesToScan="xxx.xxx"这样就不用写annotatedClasses属性-->
<propertyname="annotatedClasses">
<list>
<value>com.baobaotao.User</value>
</list>
</property>
<propertyname="hibernateProperties">
<props>
<propkey="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<propkey="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
上面是使用导入注解的类,如果是xxx.hbm.xml配置文件,那么使用mappingLocations属性
<propertyname="mappingLocations">
<list>
<value>classpath*:/user/*.hbm.xml</value>
</list>
</property>
如果想使用hibernate.cfg.xml文件,添加<property name="configLocation" value="classpath:hibernate.cfg.xml" />即可,其他属性请看api
3.配置事务管理器
<beanid="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<propertyname="sessionFactory"ref="sessionFactory"/>
</bean>
如果你的hibernate是4.x的版本,那么使用hibernate4包下的HibernateTransactionManager
4.把事务管理器变成advice
<tx:adviceid="txAdvice"transaction-manager="transactionManager">
<tx:attributes>
<tx:methodname="list*"propagation="REQUIRED"read-only="true"/>
<tx:methodname="get*"propagation="REQUIRED"read-only="true"/>
<tx:methodname="find*"propagation="REQUIRED"read-only="true"/>
<tx:methodname="load*"propagation="REQUIRED"read-only="true"/>
<tx:methodname="save*"propagation="REQUIRED"/>
<tx:methodname="delete*"propagation="REQUIRED"/>
<tx:methodname="update*"propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
propagation可以使用的值Enumerated Values : - REQUIRED - SUPPORTS - MANDATORY -REQUIRES_NEW -NOT_SUPPORTED -NEVER - NESTED 含义参看上面的事务传播特性
5.把事务增强织入到目标方法中
<aop:config>
<aop:advisorpointcut="execution(*com.auscend..services..*.*(..))"advice-ref="txAdvice"/>
<aop:advisorpointcut="execution(*com.auscend.secure..*.*(..))" advice-ref="txAdvice"/>
</aop:config>
6.在dao中要使用session,而session从sessionFactory中取出,所以把sessionFactory注入到dao中,dao中获得session就可以通过sessionFactory.getCurrentSession()来获取当前session,也可以使用spring提供的模板类HibernateTemplate,关于这个类的api请参看api
<beanid="hibernateTemplate"
class="org.springframework.orm.hibernate3.HibernateTemplate">
<propertyname="sessionFactory"ref="sessionFactory"></property>
</bean>
如果spring使用注解来实现的话,那么在类上和方法上,使用@Transactional,在spring的配置文件中添加<tx:annotation-driven transaction-manager="transactionManager"/> 如果transaction-manager的值就是transactionManager的话可以省略。如果在一个类上这个类中的方法上同时注解了@Transactional属性值不同,那么方法上的注解优先
使用了@Transactional就没必要在配置文件中配置事务增强代码和事务代码的自动织入了
@Transactional的属性
isolation | |
>[] | noRollbackFor |
noRollbackForClassName | |
propagation | |
boolean | readOnly |
Class<?extendsThrowable>[] | rollbackFor |
rollbackForClassName | |
timeout | |
String | value |