Spring笔记----Day03----事务控制

一、JdbcTemplate:

1、使用之前,需要导入的jar包:

spring-jdbc-5.0.2.RELEASE.jar
spring-tx-5.0.2.RELEASE.jar

2、spring的事务控制的API:

<1>、PlatformTransactionManager:

(1)、作用:

该接口是提供事务操作的方法。

(2)、具体操作方法:

①、获取事务状态信息:
TransactionStatus getTransaction(TransactionDefinition definition)
②、提交事务:
void commit(TransactionStatus status)
③、回滚事务:
void rollback(TransactionStatus status)

(2)、具体管理事务(实现类)的对象:

①、使用Spring JDBC或iBatis进行持久化数据时使用:
 org.springframework.jdbc.datasource.DataSourceTransactionManager、
②、使用Hibernate版本进行持久化数据时使用:
org.springframework.orm.hibernationManager

<2>、TransactionDefinition:

(1)、作用:

该接口是提供事务定义的对象。

(2)、具体操作方法:

①、获取事务对象名称:
String getName()
②、获取事务隔离级别:
Ⅰ、方法名:
int getIsolationLevel()
Ⅱ、方法参数:
ISOLATION_DEFAULT:默认级别,归属下面某一种。
ISOLATION_READ_UNCOMMITTED:可以读未提交数据
ISOLATION_READ_COMMITTED只能读取已提交数据,解决脏读问题(Oracle默认级别)
ISOLATION_REPETABLE_READ:是否读取其他事务提交修改后的数据,解决不可重复读问题(MYSQL默认级别)
ISOLATION_SERIALIZABLE:是否读取其他事务提交添加后的数据,解决幻读问题
③、获取事务传播行为:
Ⅰ、方法名:
int getPropagationBehavior()
Ⅱ、方法参数:
REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,就加入到该事务中。一般的选择,默认值。
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。
REQUERS_NEW:新建事务,如果当前在事务中,就把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER:以非事务方式运行,如果当前存在事务,就抛出异常。
NESTED:如果当前存在事务,则在嵌套事务内执行;如果没有事务,则执行REQUIRED类似的操作。
④、获取事务超时时间:
Ⅰ、方法名:
int getTimeout()
Ⅱ、方法参数:
默认值是-1,没有超时限制。如果有,以秒为单位进行设置。
⑤、获取事务是否只读:
Ⅰ、方法名:
boolean isReadOnly()
Ⅱ、方法参数:
建议查询时设置为只读。

<3>、TransactionStatus:

(1)、作用:

描述了某个时间点上事务对象的状态信息。

(2)、具体操作方法:

①、刷新事务:
void flush()
②、获取是否存在存储点:
boolean hasSavepoint()
③、获取事务是否完成:
boolean isCompleted()
④、获取事务是否为新事务:
boolean isNewTransaction()
⑤、获取事务是否回滚:
boolean isRollbackOnly()
⑥、设置事务回滚:
void setRollbackOnly()

二、配置:

1、在XML中配置JdbcTemplate的方法:


    
        
    

2、JdbcTemplate的操作:

<1>、获取容器:

ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

<2>、获取对象:

JdbcTemplate jt = ac.getBean("jdbcTemplate",JdbcTemplate.class);

<3>、保存操作:

jt.update("insert into account(name,money)values(?,?)","ttt",3333f);

<4>、更新操作:

jt.update("update account set name = ?,money = ? where id = ?;","aaa",1234,1);

<5>、删除操作:

jt.update("delete from account where id = ?",11);

<6>、查询所有:

List accounts1 =
                jt.query("select * from account where money > ?", new AccountRowMapper(),4000f);
List accounts2 =
                jt.query("select * from account where money > ?", new BeanPropertyRowMapper(Account.class),4000f);
for(Account account : accounts1){
  System.out.println(account);
}

<7>、查询一个:

List accounts =
                jt.query("select * from account where money > ?", new BeanPropertyRowMapper(Account.class),4000f);
System.out.println(accounts.isEmpty()? "没有内容" : accounts.get(0));

<8>、查询返回一行一列(使用聚会函数,但不加group by子句):

Long count = jt.queryForObject("Select count(*) from account where money > ?",Long.class,1000f);
System.out.println(count);

2、pring中基于xml的声明式事务配置步骤:

<1>.配置事务管理器:

    
        
    

<2>.配置事务通知:

(1)、注意:

此时需要导入事务的约束;包括tx的名称空间和约束,aop的名称空间和约束。  

(2)、使用tx:advice标签配置事务通知时:

id:给事务通知起一个唯一id
transaction-manager:给事务通知提供一个事务管理引用

(3)、配置代码:


        
        
            
            
        
    

<3>、配置AOP中的通用切入点表达式:


        
        

        
        
    

<4>、配置事务属性:

(1)、注意:

在事务的通知tx:Advice标签内部配。

(2)、tx:method标签属性:

①、isolation="" :
用于指定事务的隔离级别,默认值是default,表示使用数据库的隔离属性
②、propagation="" :
用于指定事务的传播行为。默认值REQUIRED,表示一定会有事务。增删改的选择。查询方法可以选SUPPORTS。
③、read-only="" :
用于指定事务是否只读。只有查询方法才能设置为True,默认值是false,表示读写。
④、timeout="":
用于指定事务的超时时间。默认值是-1,表示永不超时。如果指定了数值,以秒为单位。
⑤、rollback-for="" :
用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务都不回滚。没有默认值,表示任何异常都回滚。
⑥、no-rollback-for="" :
用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回滚。没有默认值,表示任何异常都回滚。

<5>.配置数据源:

//1.准备数据源,spring的内置数据源
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/eesy");
ds.setUsername("root");
ds.setPassword("123456");

//2.创建对象
JdbcTemplate jt = new JdbcTemplate();

//3.给对象设置数据源
jt.setDataSource(ds);

//3.执行操作
jt.execute("insert into account(name,money)values('SSS',2222)");

3、pring中基于注解的声明式事务配置步骤:

<1>.配置要扫描的包:


<2>.配置JdbcTemplate:


        
    

<3>.配置数据源:


        
        
        
        
    

<4>.配置事务管理器:


        
    

<5>.开启spring对注解事务的支持:


<6>.在需要事务支持的地方使用@Transaal注解:

//只读型事务配置,配置在类上
@Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
 //读写型事务配置,配置在方法上
@Transactional(propagation = Propagation.REQUIRED,readOnly = false)

三、配置完全代码:

1、基于XML的配置:

<1>、在JdbcTemplate类中:

public class JdbcTemplateDemo1 {
    public static void main(String[] args) {
        //1.准备数据源,spring的内置数据源
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/eesy");
        ds.setUsername("root");
        ds.setPassword("123456");

        //2.创建对象
        JdbcTemplate jt = new JdbcTemplate();

        //3.给对象设置数据源
        jt.setDataSource(ds);

        //3.执行操作
        jt.execute(SQL操作语句");
    }
}

<2>、在bean.xml中:

bean.xml中:

    
        
    

    
    
        
    

    
    
        
        
        
        
    

    
    
        
    

    
    
        
        
            
            
        
    

    
    
        
        

        
        
    

<3>、Service层:

public class AccountService implements IAccountService {

    private IAccountDao accountDao;

    public void setAccountDao(IAccountDao accountDao) {
        this.accountDao = accountDao;
    }

    public Account findAccountById(Integer accountId) {
        return accountDao.findAccountById(accountId);
    }

    public void transfer(String sourceName, String targetName, Float money) {
        System.out.println("transfer!!!");
        //根据名称查询转出账户
        Account source = accountDao.findAccountByName(sourceName);
        //根据名称查询转入账户
        Account target = accountDao.findAccountByName(targetName);
        //转出账户减钱
        source.setMoney(source.getMoney() - money);
        //转入账户加钱
        target.setMoney(target.getMoney() + money);
        //更新转出账户
        accountDao.updateAccount(source);
        //更新转入账户
        accountDao.updateAccount(target);
    }
}

<4>、Dao层:

public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {

    public Account findAccountById(Integer accountId) {
        List accounts = super.
                getJdbcTemplate().query("select * from account where money > ?", new BeanPropertyRowMapper(Account.class), accountId);
        return accounts.isEmpty() ? null : accounts.get(0);
    }

    public Account findAccountByName(String accountName) {
        List accounts = super.
                getJdbcTemplate().query("select * from account where name = ?", new BeanPropertyRowMapper(Account.class),accountName);
        if(accounts.isEmpty()){
            return null;
        }
        if(accounts.size() > 1){
            throw new RuntimeException("结果集不唯一!!!");
        }
        return accounts.get(0);
    }

    public void updateAccount(Account account) {
        super.getJdbcTemplate().update("update account set name = ?,money = ? where id = ?",account.getName(),account.getMoney(),account.getId());
    }
}

<5>、定义account的封装策略:

class AccountRowMapper implements RowMapper{
    /**
     * 把结果集中的数据封装到account中,然后由spring把每个Account加到集合中
     * @param rs
     * @param i
     * @return
     * @throws SQLException
     */
    public Account mapRow(ResultSet rs, int i) throws SQLException {
        Account account = new Account();
        account.setId(rs.getInt("id"));
        account.setName(rs.getString("name"));
        account.setMoney(rs.getFloat("money"));
        return account;
    }

2、基于注解的配置:

<1>、在bean.xml中:

    
    

    
    
        
    

    
    
        
        
        
        
    

    
    
        
    

    
    

<2>、Service层:

@Service("accountService")
//只读型事务配置
@Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
public class AccountServiceImpl implements IAccountService {

    @Autowired
    private IAccountDao accountDao;

    public Account findAccountById(Integer accountId) {
        return accountDao.findAccountById(accountId);
    }


    //读写型事务配置
    @Transactional(propagation = Propagation.REQUIRED,readOnly = false)
    public void transfer(String sourceName, String targetName, Float money) {
        System.out.println("transfer!!!");
        //根据名称查询转出账户
        Account source = accountDao.findAccountByName(sourceName);
        //根据名称查询转入账户
        Account target = accountDao.findAccountByName(targetName);
        //转出账户减钱
        source.setMoney(source.getMoney() - money);
        //转入账户加钱
        target.setMoney(target.getMoney() + money);
        //更新转出账户
        accountDao.updateAccount(source);
        int i =  1/0;
        //更新转入账户
        accountDao.updateAccount(target);
    }
}

<3>、Dao层:

@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public Account findAccountById(Integer accountId) {
        List accounts = jdbcTemplate.query("select * from account where money > ?", new BeanPropertyRowMapper(Account.class), accountId);
        return accounts.isEmpty() ? null : accounts.get(0);
    }

    public Account findAccountByName(String accountName) {
        List accounts = jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper(Account.class),accountName);
        if(accounts.isEmpty()){
            return null;
        }
        if(accounts.size() > 1){
            throw new RuntimeException("结果集不唯一!!!");
        }
        return accounts.get(0);
    }

    public void updateAccount(Account account) {
        jdbcTemplate.update("update account set name = ?,money = ? where id = ?",account.getName(),account.getMoney(),account.getId());
    }
}

<4>、JdbcTemplate:

public class JdbcTemplateDemo1 {
    public static void main(String[] args) {
        //1.准备数据源,spring的内置数据源
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/eesy");
        ds.setUsername("root");
        ds.setPassword("123456");

        //2.创建对象
        JdbcTemplate jt = new JdbcTemplate();

        //3.给对象设置数据源
        jt.setDataSource(ds);

        //3.执行操作
        jt.execute("insert into account(name,money)values('SSS',2222)");
    }
}

你可能感兴趣的:(Spring笔记----Day03----事务控制)