Spring管理事物

原文转自:获取

Spring的早期版本用户必须通过TransactionProxyFactoryBean代理对需要事务管理的业务类进行代理,便于实施事务功能的增强。
让我们先看代码吧!
业务层代码:

?
1
2
3
4
5
public interface UserScoreService {
     public UserScore getUserSocore(String userNo);
     public void addUserScore(UserScore us);
     public int getUsableScore(String userNo);
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class UserScoreServiceImpl implements UserScoreService {
     private UserScoreRepository userScoreRepository;
     public void setUserScoreRepository(UserScoreRepository userScoreRepository) {
         this .userScoreRepository = userScoreRepository;
     }
     @Override
     public UserScore getUserSocore(String userNo) {
         return userScoreRepository.getUserSocore(userNo);
     }
     @Override
     public void addUserScore(UserScore us) {
         userScoreRepository.addUserScore(us);
     }
     @Override
     public int getUsableScore(String userNo) {
         return userScoreRepository.getUsableScore(userNo);
     }
}

持久层代码:

?
1
2
3
4
5
public interface UserScoreRepository {
     public UserScore getUserSocore(String userNo);
     public void addUserScore(UserScore us);
     public int getUsableScore(String userNo);
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class UserScoreRepositoryImpl implements UserScoreRepository {
     private JdbcTemplate jdbcTemplate;
     public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
         this .jdbcTemplate = jdbcTemplate;
     }
     @Override
     public UserScore getUserSocore(String userNo) {
         
         final UserScore us = new UserScore();
         
         StringBuffer sql = new StringBuffer();
         sql.append( "select * from userscore where userNo = ?" );
         
         jdbcTemplate.query(sql.toString(), new Object[]{userNo}, new RowCallbackHandler() {
             
             @Override
             public void processRow(ResultSet rs) throws SQLException {
                 us.setId(rs.getInt( "id" ));
                 us.setHonourScore(rs.getInt( "honourScore" ));
                 us.setUsableScore(rs.getInt( "usableScore" ));
                 us.setUserName(rs.getString( "userName" ));
                 us.setUserNo(rs.getString( "userNo" ));
             }
         });
         return us;
     }
     @Override
     public void addUserScore(UserScore us) {
     }
     @Override
     public int getUsableScore(String userNo) {
         return 0 ;
     }
 
}

Spring配置文件:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!-- 定义一个数据源 -->
< bean id = "dataSource" class = "org.apache.tomcat.jdbc.pool.DataSource" >
     < property name = "driverClassName" value = "com.mysql.jdbc.Driver" />
     < property name = "url" value = "jdbc:mysql://localhost:3306/spring_test" />
     < property name = "username" value = "root" />
     < property name = "password" value = "root" />
</ bean >
 
<!-- 定义JdbcTemplate的Bean -->
< bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate"
     p:dataSource-ref = "dataSource" >
</ bean >
 
< bean id = "userScoreRepository_jdbc"
     class = "net.hingyi.springDemo.transaction.repository.UserScoreRepositoryImpl"
     p:jdbcTemplate-ref = "jdbcTemplate" />
     
 
<!-- 声明事务管理器 -->
< bean id = "txManager"
     class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" >
     < property name = "dataSource" ref = "dataSource" ></ property >
</ bean >
 
<!-- 需要实施事务增强的目标业务Bean -->
< bean id = "userScoreTarget"
     class = "net.hingyi.springDemo.transaction.service.UserScoreServiceImpl"
     p:userScoreRepository-ref = "userScoreRepository_jdbc" />
     
<!-- 使用事务代理工厂类为目标业务Bean提供事务增强 -->
<!-- p:transactionManager-ref="txManager"  指定事务管理器 -->
<!-- p:target-ref="userScoreTarget" 指定目标业务Bean -->
< bean id = "userScore" class = "org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
     p:transactionManager-ref = "txManager"
     p:target-ref = "userScoreTarget" >
     
     < property name = "transactionAttributes" >
         < props >
             < prop key = "get*" >PROPAGATION_REQUIRED,readOnly</ prop >   <!-- 只读事务 -->
             < prop key = "*" >PROPAGATION_REQUIRED</ prop >   <!-- 可写事务 -->
         </ props >
     </ property >
     
</ bean >

 

web.xml配置

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
< context-param >
     < param-name >log4jConfigLocation</ param-name >
     < param-value >classpath:log4j.properties</ param-value >
</ context-param >
< context-param >
     < param-name >contextConfigLocation</ param-name >
     < param-value >classpath:applicationContext.xml</ param-value >
</ context-param >
 
< listener >
     < listener-class >org.springframework.web.util.Log4jConfigListener</ listener-class >
</ listener >
< listener >
     < listener-class >org.springframework.web.context.ContextLoaderListener</ listener-class >
</ listener >

 

异常回滚/提交规则
上面spring配置中的<prop>内的值为事务属性信息,匹配格式为:

PROPAGATION

(传播行为)

扫描二维码关注公众号,回复: 489417 查看本文章

ISOLATION

(隔离级别(可选))

readOnly

(是否为只读事务(可选))

-Exceptions

(发生这些异常时回滚事务(可选))

 

+Exceptions

(发生这些异常时照样提交事务(可选))


Spring事务的传播类型
Spring在TransactionProxyFactory接口中规定了7种类型的事务传播行为,它们规定了事务方法和事务发生嵌套调用时候是怎么传播的。如:

事务传播行为类型

说明

PROPAGATION_REQUIRED

如果当前没有事务,就新建一个事务;如果已经存在一个事务,加入到这个事务中。(这个是最常见的选择)

PROPAGATION_SUPPORTS

支持当前事务。如果当前没有事务,就以非事务方式执行

PROPAGATION_MANDATORY

使用当前的事务。如果当前没有事务,就抛出异常

PROPAGATION_REQUIRES_NEW

新建事务。如果当前存在事务,就把当前事务挂起

PROPAGATION_NOT_SUPPORTED

以非事务的方式执行操作。如果当前存在事务,就把当前事务挂起

PROPAGATION_NEVER

以非事务方式执行。如果当前存在事务,则抛出异常

PROPAGATION_NESTED

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与

PROPAGATION_REQUIRED类似的操作


隔离级别
隔离级别是可选的,默认的为ISOLATION_DEFAULT,表示数据库的默认隔离级别。隔离级别的值如下:

隔离级别

脏读

不可重复读

幻象读

第一类丢失更新

第二类丢失更新

ISOLATION_READ_UNCOMMITED

允许

允许

允许

不允许

允许

ISOLATION_READ_COMMITED

不允许

允许

允许

不允许

允许

ISOLATION_REPEATABLE_READ

不允许

不允许

允许

不允许

不允许

ISOLATION_SERIALIZABLE

不允许

不允许

不允许

不允许

不允许

 

默认情况下,当发生运行异常时,事务将被回滚,发生检查型异常时,既不回滚也不提交,控制权交给外层调用。所以,带负号的异常设置仅对检查型异常有意义。

猜你喜欢

转载自yangyangcom.iteye.com/blog/2197571