您的位置:

Spring事物管理的实现

一、简述spring中事物管理的两种方式

Spring中事物管理有两种方式,分别是编程式事物管理和声明式事物管理。编程式事物管理就是在代码中手动控制事物的开启、提交和回滚;而声明式事物管理则是通过配置文件或注解的方式来声明哪些方法需要开启事物,并自动实现事物的管理。

二、Spring事物管理方式

1. Spring事物管理接口

Spring事物管理接口是org.springframework.transaction包中定义的事物管理的基本接口。

public interface PlatformTransactionManager {
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
    void commit(TransactionStatus status) throws TransactionException;
    void rollback(TransactionStatus status) throws TransactionException;}

getTransaction方法用于获取事物的状态,commit方法用于提交事物,rollback方法用于回滚事物。这三个方法是Spring事物机制中最基本的方法。

2. Spring事物管理的核心接口

Spring事物管理的核心接口是TransactionDefinition和TransactionStatus这两个接口。

public interface TransactionDefinition {
    int PROPAGATION_REQUIRED = 0;
    int ISOLATION_DEFAULT = -1;
    int TIMEOUT_DEFAULT = -1;
    int getPropagationBehavior();
    int getIsolationLevel();
    int getTimeout();
    boolean isReadOnly();
    String getName();}
 
public interface TransactionStatus extends SavepointManager {
    boolean isNewTransaction();
    boolean hasSavepoint();
    void setRollbackOnly();
    boolean isRollbackOnly();
    void flush();}

TransactionDefinition接口定义了事物的传播属性、隔离级别、超时时间、只读属性和事务名称等属性。TransactionStatus接口则定义了事物的状态,比如是否是新事物、是否有保存点、是否只回滚、是否已经完成等。

三、Spring中的事物是如何实现的

在Spring事物管理中,需要对数据源进行事物管理的方法被标注为@Transactional,Spring将会在方法执行前开启一个事物,方法执行后,如果出现异常,则回滚事物,否则提交事物。

1. Spring事物管理的两种方式

事务管理有两种方式:程序式事务管理和声明式事务管理。

2. Spring事物的实现方式

Spring提供了几种不同的实现事物的方式。

(1)编程式事务管理

编程式事务管理就是在代码中手动控制事物的开启、提交和回滚。

public class AccountServiceImpl implements AccountService {
    // 使用@Resource注解注入DataSource对象
    @Resource(name = "dataSource")
    private DataSource dataSource;
    @Override
    public void transfer(String fromUser, String toUser, double money) throws Exception {
        Connection conn = null;
        PreparedStatement pstmt1 = null;
        PreparedStatement pstmt2 = null;
        try {
            conn = dataSource.getConnection();
            // 开启事物
            conn.setAutoCommit(false);
            String sql1 = "update account set balance = balance - ? where username = ?";
            String sql2 = "update account set balance = balance + ? where username = ?";
            pstmt1 = conn.prepareStatement(sql1);
            pstmt1.setDouble(1, money);
            pstmt1.setString(2, fromUser);
            pstmt1.executeUpdate();
            pstmt2 = conn.prepareStatement(sql2);
            pstmt2.setDouble(1, money);
            pstmt2.setString(2, toUser);
            pstmt2.executeUpdate();
            // 提交事物
            conn.commit();
        } catch (Exception e) {
            // 回滚事物
            conn.rollback();
            throw e;
        } finally {
            if (pstmt1 != null) {
                pstmt1.close();
            }
            if (pstmt2 != null) {
                pstmt2.close();
            }
            if (conn != null) {
                conn.close();
            }
        }
    }
}
(2)声明式事务管理

声明式事务管理则是通过配置文件或注解的方式来声明哪些方法需要开启事物,并自动实现事物的管理。

在XML配置文件中声明事物管理:



    
   

  


在Java类中使用@Transactional注解声明事物管理:

@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;
    @Override
    @Transactional
    public void transfer(String fromUser, String toUser, double money) throws Exception {
        accountDao.update(fromUser, -money);
        //int i = 1 / 0;
        accountDao.update(toUser, money);
    }
}

3. Spring事物实现过程的示例

以Spring注解方式实现转账为例,下面是完整的代码示例:

Account类:

public class Account {
    private int id;
    private String username;
    private double balance;
    // getter/setter方法省略
}

AccountDao接口:

public interface AccountDao {
    public void update(String username, double money) throws Exception;
    public Account findByUsername(String username) throws Exception;}

AccountDao实现类:

@Repository
public class AccountDaoImpl implements AccountDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Override
    public void update(String username, double money) throws Exception {
        String sql = "update account set balance = balance + ? where username = ?";
        jdbcTemplate.update(sql, money, username);
    }
    @Override
    public Account findByUsername(String username) throws Exception {
        String sql = "select * from account where username = ?";
        List list = jdbcTemplate.query(sql, new Object[]{username}, new AccountRowMapper());
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }
    private class AccountRowMapper implements RowMapper
    {
        @Override
        public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
            Account account = new Account();
            account.setId(rs.getInt("id"));
            account.setUsername(rs.getString("username"));
            account.setBalance(rs.getDouble("balance"));
            return account;
        }
    }
}

   
  

AccountService接口:

public interface AccountService {
    public void transfer(String fromUser, String toUser, double money) throws Exception;
    public Account findByUsername(String username) throws Exception;}

AccountService实现类:

@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;
    @Override
    @Transactional
    public void transfer(String fromUser, String toUser, double money) throws Exception {
        Account account1 = accountDao.findByUsername(fromUser);
        Account account2 = accountDao.findByUsername(toUser);
        double balance1 = account1.getBalance() - money;
        double balance2 = account2.getBalance() + money;
        accountDao.update(fromUser, -money);
        // 手动制造一个异常,测试事物管理是否起作用
        int i = 1 / 0;
        accountDao.update(toUser, money);
    }
    @Override
    public Account findByUsername(String username) throws Exception {
        return accountDao.findByUsername(username);
    }
}

测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class AccountServiceTest {
    @Autowired
    private AccountService accountService;
    @Test
    public void transfer() throws Exception {
        accountService.transfer("user1", "user2", 100);
    }
}

结语

Spring的事物管理是非常重要的功能,在实际开发中,经常需要处理涉及到数据库操作的事物问题。通过理解Spring事物管理的方式和实现机制,在实现事物管理的过程中就能提高效率,避免出现大量的重复代码,同时也可以简化代码的复杂度。