Spring(六)基于注解和纯注解的事务配置

Spring(六)基于注解和纯注解的事务配置

注解和XML的方式

创建 maven 工程并导入坐标

和基于 xml 配置方式要导入的坐标一致。

创建 spring 的配置文件导入约束并配置扫描的包
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/tx
      http://www.springframework.org/schema/tx/spring-tx.xsd
      http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

   <!--开启注解扫描-->
   <context:component-scan base-package="fun.chenqi"/>

   <bean id="jdbc" class="org.springframework.jdbc.core.JdbcTemplate">
       <property name="dataSource" ref="dataSource"/>
   </bean>

   <!--配置dbcp数据源-->
   <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
       <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
       <property name="url" value="jdbc:mysql://localhost:3306/chenqi"/>
       <property name="username" value="root"/>
       <property name="password" value="111"/>
   </bean>

   <!-- 第一步:配置事务管理器并注入数据源 -->
   <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <property name="dataSource" ref="dataSource"/>
   </bean>

   <!--第二步:在业务层使用@Transactional 注解-->

   <!-- 第三步:开启 spring 对注解事务的支持 -->
   <tx:annotation-driven transaction-manager="transactionManager"/>

</beans>
Service层
@Service
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
/**
* 该注解的属性和 xml 中的属性含义一致。
* 该注解可以出现在接口上,类上和方法上。
* 出现接口上,表示该接口的所有实现类都有事务支持。
* 出现在类上,表示类中所有方法有事务支持
* 出现在方法上,表示方法有事务支持。
* 以上三个位置的优先级:方法>类>接口
*/
public class AccountServiceImpl implements IAccountService {
 
   @Autowired
   IAccountDao dao;

   @Override
   public void update(Account account) throws SQLException {
       dao.update(account);
   }

   // 转账
   @Override
   @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
   /**propagation属性:
    * REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选 择(默认值)
    * SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
    * MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常
    * REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起。
    * NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
    * NEVER:以非事务方式运行,如果当前存在事务,抛出异常
    * NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行REQUIRED 类似的操作。
    */
   public void transfer(String sourceName, String targetName, Float money) throws SQLException {
       Account accountByName1 = dao.findAccountByName(sourceName);
       Account accountByName2 = dao.findAccountByName(targetName);
       accountByName1.setMoney(accountByName1.getMoney() - money);
       accountByName2.setMoney(accountByName2.getMoney() + money);
       dao.update(accountByName1);
       int i = 1 / 0;
       dao.update(accountByName2);

   }
}
Dao层
@Repository
public class AccountDaoImpl implements IAccountDao {

   @Autowired
   JdbcTemplate jdbcTemplate;

   @Override
   public void update(Account account) throws SQLException {
       String sql = "update account set money = ? where id = ? ";
       int i = jdbcTemplate.update(sql, account.getMoney(), account.getId());
       if (i > 0) {
           System.out.println("OK!");
       }
   }
   @Override
   public Account findAccountByName(String name) {
       String sql = "select * from account where name = ?";
       Account account = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Account>(Account.class), name);
       if (account != null) {
           return account;
       } else {
           return null;
       }
   }
}

纯注解:

删掉bean.xml,

pom.xml和上方保持一致

jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///chenqi
jdbc.username=root
jdbc.password=111
Service
@Service
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public class AccountServiceImpl implements IAccountService {
   @Autowired
   IAccountDao dao;
 // ......
   }
}
Dao
@Repository
public class AccountDaoImpl implements IAccountDao {
   @Autowired
   JdbcTemplate jdbcTemplate;
 // ......
}

工具类:

JdbcConfig.java
/**
* jdbc的配置类
*/
public class JdbcConfig {
   @Value("${jdbc.driver}")
   private String driver;
   @Value("${jdbc.url}")
   private String url;
   @Value("${jdbc.username}")
   private String username;
   @Value("${jdbc.password}")
   private String password;

   @Bean
   public JdbcTemplate getJdbcTemp(DataSource dataSource) {
       return new JdbcTemplate(dataSource);
   }

   @Bean
   public DataSource createDataSource() {
       try {
           BasicDataSource basicDataSource = new BasicDataSource();
           basicDataSource.setDriverClassName(driver);
           basicDataSource.setUrl(url);
           basicDataSource.setUsername(username);
           basicDataSource.setPassword(password);
           return basicDataSource;
       } catch (Exception e) {
           throw new RuntimeException();
       }
   }
}
TransactionManagerConfig.java
/**
* 事务管理的配置类
*/
public class TransactionManagerConfig {
   @Bean("transactionManager")
   public DataSourceTransactionManager createDataSourceTransactionManager(DataSource dataSource){
       return new DataSourceTransactionManager(dataSource);
   }
}
SpringConfiguration.java
/**
* Spring的配置类
*/
@Configuration
@ComponentScan("fun.chenqi")
@Import({JdbcConfig.class, TransactionManagerConfig.class})
@PropertySource("classpath:jdbc.properties")
@EnableTransactionManagement//开启事务支持
public class SpringConfiguration {
}
测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class AccountTest {
   @Autowired
   private IAccountService service;
@Test
   public void zhuan() {
       try {
           service.transfer("aaa", "bbb", 100F);
       } catch (SQLException e) {
           e.printStackTrace();
       }

   }
}


发表评论