事务的处理一般来说有两种方式:
一个是依赖特定的资源的事务:如通过JDBC,JTA,Hibernate Transaction。
还有一个就是依赖窗口的参数进行事务管理,像EJB容器事务
spring对于以上两种都有相应的实现,还提供了一些辅助类可供我们选择使用,如基于JDBC,JDO,HIBERNATE的扩展类.而对于依赖 容器的参数化事务管理来说,spring体现出一它的优势,它本身也是一个容器,但相对EJB容器它来它显得很轻巧(当然在后来插件越来越多的情况下,我 们需要摈弃一些我们不用的模块)。我们不用付出其他的代价,就可以通过spring实现容器的事务管理。
下面就来说说基于JDBC,HIBERNATE这两种方式的事务管理与非事务管理的配置:
取得source连接
首先对于一个DB操作,我们必须要取得DB连接,而在spring下取得这个连接的方式可以采用
1.JNDI
2.配置dataSource(spring方式)或者sessionFactory(hibernate)
且看下面代码:
对于JNDI可以参考如下实现:
- <bean id= "dataSource" class = "org.springframework.jndi.JndiObjectFactoryBean" >
- <property name="jndiName" >
- <value>jdbc_sdcf</value>
- </property>
- </bean>
- </beans>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>jdbc_sdcf</value>
</property>
</bean>
</beans>
对于dataSource方式如下:
- <bean id= "dataSource"
- class = "org.springframework.jdbc.datasource.DriverManagerDataSource" >
- <property name="driverClassName" >
- <value>oracle.jdbc.driver.OracleDriver</value>
- </property>
- <property name="url" >
- <value>jdbc:oracle:thin:@127 .0. 0.1 : 1521 :oracle</value>
- </property>
- <property name="username" >
- <value>test</value>
- </property>
- <property name="password" >
- <value>test</value>
- </property>
- <property name="connectionProperties" >
- <props />
- </property>
- </bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@127.0.0.1:1521:oracle</value>
</property>
<property name="username">
<value>test</value>
</property>
<property name="password">
<value>test</value>
</property>
<property name="connectionProperties">
<props />
</property>
</bean>
而对于sessionFactory的方式来说, 我们可以有两种方式来配置它:
一个是基于在spring的dataSource方式上进行配置:
- <bean id= "sessionFactory" class = "org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
- <property name="dataSource" >
- <ref local="dataSource" />
- </property>
- <property name="mappingResources" >
- <list>
- <value>com/lgh/hibernate/UserTable.hbm.xml</value>
- </list>
- </property>
- <property name="hibernateProperties" >
- <props>
- <prop key="hibernate.dialect" >org.hibernate.dialect.OracleDialect</prop>
- <prop key="hibernate.show_sql" > true </prop>
- </props>
- </property>
- </bean>
<bean id="sessionFactory" class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource"/>
</property>
<property name="mappingResources">
<list>
<value>com/lgh/hibernate/UserTable.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
而另一个方式就是在hibernate.hbm.xml方式上进行配置:
- <bean id= "sessionFactory" class = "org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
- <property name="configLocation" value= "classpath:hibernate.cfg.xml" />
- <property name="configurationClass" value= "org.hibernate.cfg.AnnotationConfiguration" />
- </bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
</bean>
这个hibernate.cfg.xml方式可以利用myeclipseIDE导入hibernate功能时自动创建,如下例子:
- <?xml version= '1.0' encoding= 'UTF-8' ?>
- <!DOCTYPE hibernate-configuration PUBLIC
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd" >
- <!-- Generated by MyEclipse Hibernate Tools. -->
- <hibernate-configuration>
- <session-factory>
- <property name="dialect" >
- org.hibernate.dialect.OracleDialect
- </property>
- <property name="connection.url" >
- jdbc:oracle:thin:@localhost : 1521 :oracle
- </property>
- <property name="connection.username" >test</property>
- <property name="connection.password" >test</property>
- <property name="connection.driver_class" >
- oracle.jdbc.driver.OracleDriver
- </property>
- <property name="myeclipse.connection.profile" >
- local_oracle
- </property>
- <!-- 事务管理类型,这里我们使用JDBC Transaction
- <property name="hibernate.transaction.factory_class" >net.sf.hibernate.transaction.JDBCTransactionFactory
- </property> -->
- <mapping resource="com/lgh/hibernate/UserTable.hbm.xml" />
- </session-factory>
- </hibernate-configuration>
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<property name="dialect">
org.hibernate.dialect.OracleDialect
</property>
<property name="connection.url">
jdbc:oracle:thin:@localhost:1521:oracle
</property>
<property name="connection.username">test</property>
<property name="connection.password">test</property>
<property name="connection.driver_class">
oracle.jdbc.driver.OracleDriver
</property>
<property name="myeclipse.connection.profile">
local_oracle
</property>
<!-- 事务管理类型,这里我们使用JDBC Transaction
<property name="hibernate.transaction.factory_class">net.sf.hibernate.transaction.JDBCTransactionFactory
</property> -->
<mapping resource="com/lgh/hibernate/UserTable.hbm.xml" />
</session-factory>
</hibernate-configuration>
事务管理(transactionManager)的两种初始化方式:
一种是根据dataSource来初始化我们的事务管理器,另一种则是根据sessionFactory(hibernate方式)来初始化我们的事务管理器:
- <!-- 事务方式方式一-->
- <bean id="transactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" >
- <property name="dataSource" >
- <ref local = "dataSource" />
- </property>
- </bean>
- <!-- 事务配置方式二 -->
- <bean id="transactionManager"
- class = "org.springframework.orm.hibernate3.HibernateTransactionManager" >
- <property name="sessionFactory" ref= "sessionFactory" />
- </bean>
<!-- 事务方式方式一-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref local = "dataSource"/>
</property>
</bean>
<!-- 事务配置方式二 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
JDBC在spring下的事务与非事务方式
1.非事务处理方式
jdbc在spring下的非事务方式很简单,它其实就是于JDBC的简单封装:
- public interface JdbcDao {
- public void insert(String[] sql);
- }
- public class JdbcDaoImpl extends JdbcDaoSupport implements JdbcDao {
- public void insert(String[] sql) {
- for (String s : sql)
- getJdbcTemplate().execute(s);
- }
- }
public interface JdbcDao {
public void insert(String[] sql);
}
public class JdbcDaoImpl extends JdbcDaoSupport implements JdbcDao {
public void insert(String[] sql) {
for (String s : sql)
getJdbcTemplate().execute(s);
}
}
这是简单的SQL语句插入,对于配置文件,我们只需要配置一个dataSource跟如下的bean:
- <bean id= "jdbcDao" class = "com.lgh.spring.jdbc.JdbcDaoImpl" >
- <property name="dataSource" >
- <ref local="dataSource" />
- </property>
- </bean>
<bean id="jdbcDao" class="com.lgh.spring.jdbc.JdbcDaoImpl">
<property name="dataSource">
<ref local="dataSource"/>
</property>
</bean>
这种方式的缺点就是它是非事务处理方,即如果后面的数据处理错误时,而这时候如果前面已经进入数据操作了,它将无法回滚。
2.事务处理方式
顾名思义,这种方式是可以回滚前面所做的事情的。它的参数化配置如下:
- <bean id= "jdbcDaoProxy" class = "org.springframework.transaction.interceptor.TransactionProxyFactoryBean" >
- <property name="proxyTargetClass" >
- <value>true </value>
- </property>
- <property name="transactionManager" >
- <ref local="transactionManager" />
- </property>
- <property name="target" >
- <ref local="jdbcDao" />
- </property>
- <property name="transactionAttributes" >
- <props>
- <prop key="insert*" >PROPAGATION_REQUIRED</prop>
- <prop key="*" >PROPAGATION_REQUIRED,readOnly</prop>
- </props>
- </property>
- </bean>
<bean id="jdbcDaoProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="proxyTargetClass">
<value>true</value>
</property>
<property name="transactionManager">
<ref local="transactionManager"/>
</property>
<property name="target">
<ref local="jdbcDao"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
如果我们想默认对所有的事件进行事务处理我们可以不用配置transactionAttributes
Hibernate在spring下的事务与非事务处理方式:
非事务处理方式很简单:
- <bean id = "hiberDao" class = "com.lgh.spring.hibernate.HiberDaoImpl" >
- <property name="sessionFactory" >
- <ref local = "sessionFactory" />
- </property>
- </bean>
<bean id = "hiberDao" class = "com.lgh.spring.hibernate.HiberDaoImpl">
<property name="sessionFactory">
<ref local = "sessionFactory"/>
</property>
</bean>
而对于事务处理方式的参数化配置:
- <bean id = "hiberDaoProxy" class = "com.lgh.spring.hibernate.HiberDaoImpl" >
- <property name="sessionFactory" >
- <ref local = "sessionFactory" />
- </property>
- </bean>
- <bean id="hiberDao" class = "org.springframework.transaction.interceptor.TransactionProxyFactoryBean" >
- <property name="transactionManager" ref= "transactionManager" />
- <property name="target" ref= "hiberDaoProxy" />
- <property name="proxyInterfaces" value= "com.lgh.spring.hibernate.HiberDao" />
- <property name="transactionAttributes" >
- <props>
- <prop key="*" >PROPAGATION_REQUIRED</prop>
- </props>
- </property>
- </bean>
<bean id = "hiberDaoProxy" class = "com.lgh.spring.hibernate.HiberDaoImpl">
<property name="sessionFactory">
<ref local = "sessionFactory"/>
</property>
</bean>
<bean id="hiberDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager" />
<property name="target" ref="hiberDaoProxy" />
<property name="proxyInterfaces" value="com.lgh.spring.hibernate.HiberDao" />
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
总:
对于项目开发中,实际上经常会碰到spring与hibernate一起结合来进行参数化配置,但很多时候我们总是会分不清到底是哪个跟哪个。但其实我们 只要掌握了,事务参数化配置的原理。如如何取得sessionFactory,它有几种方式。是否要引用datasource来建立,及事务管理器的各种 参数化配置方式等等,总之,只要明白的其中的原理就不难解决配置上的这块问题了。