spring4_事务控制xml和注解的实现

前提介绍:通过上一张我们通过对手动事务的控制,达到语句错误而进行回滚 https://blog.csdn.net/weixin_46809332/article/details/115746945,而spring提供了事务的控制。

一:介绍
1. spring提供了分层涉及业务层的事务处理解决方案,提供了一组事务控制的接口,并且事务控制都是基于aop的。
2. api介绍
–2.1 PlatformTransactionManager接口提供事务操作的方法
获取事务状态信息 TransactionStatus getTransaction(TransactionDefinition definition)
提交事务 void commit(TransactionStatus status)
回滚事务 void rollback(TransactionStatus status)
真正管理事务的对象 org.springframework.jdbc.datasource.DataSourceTransactionManager 使用 Spring JDBC 或 iBatis 进行持久化数据时使用
org.springframework.orm.hibernate5.HibernateTransactionManager 使用 Hibernate 版本进行持久化数据时使用
– 2.2 TransactionDefinition
获取事务对象的名称 String getName();
获取事务的隔离级 int getIsolationLevel();
获取事务传播行为 int getPropagationBehavior();
获取事务超时时间 int getTimeout()
获取事务是否只读 boolean isReadOnly()
读写型事务:修改、删除、增加开启事务 只读型事务:执行查询时,也会开启事务
---- 事务的隔离级别
在这里插入图片描述
- --事务的传播行为
在这里插入图片描述
—超时时间
默认值是-1,没有超时限制,如果有,以秒为单位进行设置

– 2.3TransactionStatus

在这里插入图片描述
3. xml代码实现
spring中基于xml的声明事务控制步骤
– 1配置事务管理器
–2配置事务的通知
–3配置aop中通用切入点表达式
–4 建立事务通知和切入点表达式的对应关系
–5配置事务的属性
3.1 结构图
在这里插入图片描述
3.1导入pom.xml

  <artifactId>spring-jdbc</artifactId>
  <artifactId>spring-context</artifactId>'
   <artifactId>spring-tx</artifactId>
   <artifactId>aspectjweaver</artifactId>
    <artifactId>mysql-connector-java</artifactId>
    <artifactId>junit</artifactId>
    <artifactId>log4j</artifactId>

3.2 . 实体类account
在这里插入图片描述

3.3 service

public class IaccountServiceImpl implements IaccountService
{

    private IaccountDao accDao;

    public void setAccDao(IaccountDao accDao) {
        this.accDao = accDao;
    }

    public List<account> findAll() throws SQLException {
        return accDao.findAll();
    }

    public account findById(Integer id) throws SQLException {
        return accDao.findById(id);
    }

    public void updateAcc(account acc) throws SQLException {
        accDao.updateAcc(acc);
    }

    public void deleteById(Integer id) throws SQLException {
        accDao.deleteById(id);
    }

    public void insert(account acc) throws SQLException {
        accDao.insert(acc);
    }

    public void transfer(String sourceName, String targetName, float money) throws SQLException {
        //执行操作
        //获取转账人的钱数
        account aa = accDao.findByNme(sourceName);
        account bb = accDao.findByNme(targetName);
        //转账
        aa.setMoney(aa.getMoney()-money);
        bb.setMoney(bb.getMoney()+money);
        //更新
        accDao.updateAcc(aa);
         //int a=1/0;
        accDao.updateAcc(bb);
    }
    
}

3.4 dao

public class IaccountDaoImpl extends jdbcDaoSupport implements IaccountDao {
    public List<account> findAll() {
        List<account> one= getJdbcTemplate().query("select *from account",new AccountRowMapper());
        return one;
    }

    public account findById(Integer id) {
        List<account> account = getJdbcTemplate().query("select *from account where id = ?", new AccountRowMapper(), id);

        return account.isEmpty()?null:account.get(0);
    }
    public account findByNme(String name){
        List<account> account = getJdbcTemplate().query("select *from account where name = ?", new AccountRowMapper(), name);
        if (account.isEmpty()){
            return null;
        }
        if (account.size()>1){
            throw new RuntimeException("结果集不唯一。");
        }
        return account.get(0);
    }

    public void insert(account account) {

        getJdbcTemplate().update("insert  into account values(NULL ,?,?)",account.getName(),account.getMoney());
    }

    public void deleteById(Integer id) {
        getJdbcTemplate().update("delete from account whew id = ?",id);
    }

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


    protected void checkDaoConfig() throws IllegalArgumentException {

    }
}

3.5 config 这个template主要是通过spring内置的来创建

public class AccountRowMapper implements RowMapper<account> {
    public account mapRow(ResultSet resultSet, int i) throws SQLException {
        account account = new account();
        account.setId(resultSet.getInt("id"));
        account.setName(resultSet.getString("name"));
        account.setMoney(resultSet.getFloat("money"));
        return account;
    }
}
public abstract class jdbcDaoSupport  extends DaoSupport {
    private JdbcTemplate jdbcTemplate;
    //set 方法注入数据源,判断是否注入了,注入了就创建 JdbcTemplate
    public final  void  setDataSourc(DataSource dataSourc) {
        if (jdbcTemplate==null||dataSourc!=jdbcTemplate.getDataSource()){
            this.jdbcTemplate=createJdbcTemplate(dataSourc);
        }
    }
    //使用数据源注入jdbcTemplate
    protected JdbcTemplate createJdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);  }
//
//        //也可以通过注入JdbcTemplate对象
//    public  final void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
//        this.jdbcTemplate = jdbcTemplate;
//       // initTemplateConfig();
//    }

3.6bean.xm

<!--配置service-->
    <bean id="accountService" class="lml.service.IaccountServiceImpl">
        <property name="accDao" ref="accountDao"></property>
    </bean>
    <!--配置dao-->
    <bean id="accountDao" class="lml.dao.IaccountDaoImpl">
        <property name="dataSourc" ref="dataSource"></property>
    </bean>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
    <property name="url" value="jdbc:mysql://127.0.0.1:3306/springOne?serverTimezone=UTC"></property>
    <property name="username" value="root"></property>
    <property name="password" value="admin"></property>
</bean>

    <!--配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--配置事务的通知引用事务管理器 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--配置事务的属性 -->
        <tx:attributes>
            <!-- 指定方法名称:是业务核心方法
              read-only:是否是只读事务。默认 false,不只读。
              isolation:指定事务的隔离级别。默认值是使用数据库的默认隔离级别。
              propagation:指定事务的传播行为。
              timeout:指定超时时间。默认值为:-1。永不超时。
              rollback-for:用于指定一个异常,当执行产生该异常时,事务回滚。产生其他异常,事务不回滚。
                 没有默认值,任何异常都回滚。
              no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回 滚。
                  没有默认值,任何异常都回滚。
                    -->
            <tx:method name="transfer" read-only="false" propagation="REQUIRED"/>
            <tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
        </tx:attributes>

    </tx:advice>

    <!--配置aop切入点-->
    <aop:config>
        <aop:pointcut id="pt1" expression="execution(* lml.service.*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"/>
    </aop:config>
    <aop:aspectj-autoproxy  proxy-target-class="true"/>

3.7test

public class test {
    @Test
    public void one() throws SQLException {
        ClassPathXmlApplicationContext co = new ClassPathXmlApplicationContext("bean.xml");
        IaccountServiceImpl a = co.getBean("accountService",IaccountServiceImpl.class);
        a.transfer("aa","bb",100f);
    }
}

4.基于注解的代码实现
不变的是pom.xml pojo下的account
结构图
在这里插入图片描述

4.1 service
在这里插入图片描述

4.2 dao

@Component("accDao")
public class IaccountDaoImpl  implements IaccountDao {
    @Autowired
    private JdbcTemplate template;

    public List<account> findAll() {
        List<account> one= template.query("select *from account",new AccountRowMapper());
        return one;
    }

    public account findById(Integer id) {
        List<account> account = template.query("select *from account where id = ?", new AccountRowMapper(), id);

        return account.isEmpty()?null:account.get(0);
    }
    public account findByNme(String name){
        List<account> account = template.query("select *from account where name = ?", new AccountRowMapper(), name);
        if (account.isEmpty()){
            return null;
        }
        if (account.size()>1){
            throw new RuntimeException("结果集不唯一。");
        }
        return account.get(0);
    }

    public void insert(account account) {

        template.update("insert  into account values(NULL ,?,?)",account.getName(),account.getMoney());
    }

    public void deleteById(Integer id) {
        template.update("delete from account whew id = ?",id);
    }

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

4.3config

public class AccountRowMapper implements RowMapper<account> {
    public account mapRow(ResultSet resultSet, int i) throws SQLException {
        account account = new account();
        account.setId(resultSet.getInt("id"));
        account.setName(resultSet.getString("name"));
        account.setMoney(resultSet.getFloat("money"));
        return account;
    }
}
@Configuration
@PropertySource("classpath:jdbcConfig.properties")
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(name="dataSource")
    public DataSource createDataSource() throws PropertyVetoException {

        DriverManagerDataSource ds = new DriverManagerDataSource();

        ds.setUsername(username);
        ds.setPassword(password);
        ds.setDriverClassName(driver);
        ds.setUrl(url);

        return ds;
    }
    @Bean(name="template")//当使用注解时,如果有参数,spring会查找
    public JdbcTemplate createQueryRunner(DataSource dataSource)
    {
        return new JdbcTemplate(dataSource);
    }
}
@Configuration
@ComponentScan("lml")//用于指定spring在初始化容器时要扫描的包
@Import({jdbcConfig.class,TransactionConfig.class})
@EnableAspectJAutoProxy
@EnableTransactionManagement
public class SpringConfigu {
}

public class TransactionConfig {
    @Bean(name = "transactionManager")
    public PlatformTransactionManager createTransactionManager(DataSource dataSource){
        return  new DataSourceTransactionManager(dataSource);
    }
}

4.4 jdbcConfig.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springOne?serverTimezone=UTC
jdbc.username=root
jdbc.password=admin

4.5 test

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfigu.class)
public class one {
    @Autowired
    private IaccountService a;
    @Test
    public void one() throws SQLException {

        a.transfer("aa","bb",100f);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值