Spring学习第四天:JdbcTemplate,spring中的事务

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: Spring学习第四天:JdbcTemplate,spring中的事务

JdbcTemplate

依赖项

除mysql驱动以外还需要以下两个jar包

    <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.10</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.3.10</version>
        </dependency>

其中spring-tx是事务控制相关的

最基本的使用

基本使用和c3p0和dbutils差别不大

    public static void main(String[] args) {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUsername("root");
        dataSource.setPassword("adminadmin");
        dataSource.setUrl("jdbc:mysql://localhost:3306/spring_test");
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        jdbcTemplate.execute("insert into account(name,money) values('ccc',123)");
    }

写到这里我们可以注意到这里有很多语句可以使用到spring中的IOC,那么下步我们就进行对spring的配置

JdbcTemplate的IOC配置:

xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="username" value="root"/>
        <property name="password" value="adminadmin"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_test"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    </bean>
    <bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

主函数

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Bean.xml");
        JdbcTemplate jdbcTemplate = (JdbcTemplate)context.getBean("jdbcTemplate");
        jdbcTemplate.execute("insert into account(name,money) values('ccc',123)");
    }

改成原来常用的Dao模式

创建接口:

package com.spring.dao;
import com.spring.beans.Account;
import java.util.List;
/**
 * @author 28985
 */
public interface IAccountDao {
    /**
     * 查找所有
     * @return
     */
    public List<Account> findAll();
    /**
     * 根据ID查找
     * @return
     */
    public Account findById(Integer id);
    /**
     * 更新
     * @param account
     */
    public void update(Account account);
    /**
     * 删除
     * @param id
     */
    public void delete(Integer id);
    /**
     * 插入
     * @param account
     */
    public void insert(Account account);
    /**
     * 大于多少钱的人数
     * @param money
     * @return
     */
    public Integer moneyNumber(Integer money);
}

创建其实现类:

package com.spring.dao.impl;
import com.spring.beans.Account;
import com.spring.dao.IAccountDao;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
/**
 * @author 28985
 */
public class AccountDao implements IAccountDao {
    private JdbcTemplate jdbcTemplate;
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    @Override
    public List<Account> findAll() {
        return jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
    }
    @Override
    public Account findById(Integer id) {
        try {
            return jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<Account>(Account.class),id).get(0);
        }
        catch (Exception e){
            Account account =new Account();
            account.setName("NOTFOUND");
            return account;
        }
    }
    @Override
    public void update(Account account) {
        jdbcTemplate.update("update account set name = ?,money = ? where id = ?",account.getName(),account.getMoney(),account.getId());
    }
    @Override
    public void delete(Integer id) {
        jdbcTemplate.update("delete from account where id = ?",id);
    }
    @Override
    public void insert(Account account) {
        jdbcTemplate.update("insert into account(name,money) values(?,?)",account.getName(),account.getMoney());
    }
    @Override
    public Integer moneyNumber(Integer money) {
        return jdbcTemplate.queryForObject(" select count(*) from account where money > ? ", Integer.class, 900);
    }
}

再进行springIOC的配置即可使用

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean name="dao" class="com.spring.dao.impl.AccountDao">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>
    <bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="username" value="root"/>
        <property name="password" value="adminadmin"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_test"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    </bean>
  <bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
  </bean>
</beans>

进行到这里,我们会发现一个问题,如果我们有多个dao接口的实现类,他们其中的

    private JdbcTemplate jdbcTemplate;
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

这段代码是重复的

此时我们便可以提取这段代码 创建AccountDaoSupper类

package com.spring.dao.impl;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
public class AccountDaoSupper {
    private JdbcTemplate jdbcTemplate;
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }
    public void setDatasource(DataSource dataSource){
        jdbcTemplate = new JdbcTemplate(dataSource);
    }
}

然后再创建dao时就可以extends AccountDaoSupper implements IAccountDao

对应的其中所有对jdbcTemplate都将改为getJdbcTemplate()

改后效果是这样的:

package com.spring.dao.impl;
import com.spring.beans.Account;
import com.spring.dao.IAccountDao;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
/**
 * @author 28985
 */
public class AccountDao extends AccountDaoSupper implements IAccountDao {
    @Override
    public List<Account> findAll() {
        return getJdbcTemplate().query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
    }
    @Override
    public Account findById(Integer id) {
        try {
            return getJdbcTemplate().query("select * from account where id = ?", new BeanPropertyRowMapper<Account>(Account.class),id).get(0);
        }
        catch (Exception e){
            Account account =new Account();
            account.setName("NOTFOUND");
            return account;
        }
    }
    @Override
    public void update(Account account) {
        getJdbcTemplate().update("update account set name = ?,money = ? where id = ?",account.getName(),account.getMoney(),account.getId());
    }
    @Override
    public void delete(Integer id) {
        getJdbcTemplate().update("delete from account where id = ?",id);
    }
    @Override
    public void insert(Account account) {
        getJdbcTemplate().update("insert into account(name,money) values(?,?)",account.getName(),account.getMoney());
    }
    @Override
    public Integer moneyNumber(Integer money) {
        return getJdbcTemplate().queryForObject(" select count(*) from account where money > ? ", Integer.class, 900);
    }
}

然后再进行xml的修改:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean name="dao" class="com.spring.dao.impl.AccountDao">
        <property name="datasource" ref="dataSource"/>
    </bean>
    <bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="username" value="root"/>
        <property name="password" value="adminadmin"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_test"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    </bean>
</beans>

但实际上AccountDaoSupper中的代码Spring已经为我们提供好了,我们删除掉AccountDaoSupper换成继承JdbcDaoSupport这时便可以实现相同功能,而无需创建AccountDaoSupper了

package com.spring.dao.impl;
import com.spring.beans.Account;
import com.spring.dao.IAccountDao;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import java.util.List;
/**
 * @author 28985
 */
public class AccountDao extends JdbcDaoSupport implements IAccountDao {
    @Override
    public List<Account> findAll() {
        return getJdbcTemplate().query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
    }
    @Override
    public Account findById(Integer id) {
        try {
            return getJdbcTemplate().query("select * from account where id = ?", new BeanPropertyRowMapper<Account>(Account.class),id).get(0);
        }
        catch (Exception e){
            Account account =new Account();
            account.setName("NOTFOUND");
            return account;
        }
    }
    @Override
    public void update(Account account) {
        getJdbcTemplate().update("update account set name = ?,money = ? where id = ?",account.getName(),account.getMoney(),account.getId());
    }
    @Override
    public void delete(Integer id) {
        getJdbcTemplate().update("delete from account where id = ?",id);
    }
    @Override
    public void insert(Account account) {
        getJdbcTemplate().update("insert into account(name,money) values(?,?)",account.getName(),account.getMoney());
    }
    @Override
    public Integer moneyNumber(Integer money) {
        return getJdbcTemplate().queryForObject(" select count(*) from account where money > ? ", Integer.class, 900);
    }
}

spring中的事务

在需要事务时我们可以使用spring-tx这个jar包来进行事务管理

那么先进行maven导包的配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>spring_day04_06TX_zhujie</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.9</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.10</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.3.10</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.8.M1</version>
        </dependency>
    </dependencies>
</project>

首先我们先看看xml版本

首先最基本的当然是创建数据库封装的bean对象

package com.spring.beans;
/**
 * @author 28985
 */
public class Account {
    private int id;
    private String name;
    private float money;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public float getMoney() {
        return money;
    }
    public void setMoney(float money) {
        this.money = money;
    }
    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

再来创建 持久层Dao的接口类

package com.spring.dao;
import com.spring.beans.Account;
import java.util.List;
/**
 * @author 28985
 */
public interface IAccountDao {
    /**
     * 查找所有
     * @return
     */
    public List<Account> findAll();
    /**
     * 根据ID查找
     * @return
     */
    public Account findById(Integer id);
    /**
     * 更新
     * @param account
     */
    public void update(Account account);
    /**
     * 删除
     * @param id
     */
    public void delete(Integer id);
    /**
     * 插入
     * @param account
     */
    public void insert(Account account);
    /**
     * 大于多少钱的人数
     * @param money
     * @return
     */
    public Integer moneyNumber(Integer money);
    /**
     * 根据名称查找账户
     * @param name
     * @return
     */
    public Account findByName(String name);
}

再来创建他的实现类AccountDao

package com.spring.dao.impl;
import com.spring.beans.Account;
import com.spring.dao.IAccountDao;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import java.util.List;
/**
 * @author 28985
 */
public class AccountDao extends JdbcDaoSupport implements IAccountDao {
    @Override
    public List<Account> findAll() {
        return getJdbcTemplate().query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
    }
    @Override
    public Account findById(Integer id) {
        try {
            return getJdbcTemplate().query("select * from account where id = ?", new BeanPropertyRowMapper<Account>(Account.class),id).get(0);
        }
        catch (Exception e){
            Account account =new Account();
            account.setName("NOTFOUND");
            return account;
        }
    }
    @Override
    public void update(Account account) {
        getJdbcTemplate().update("update account set name = ?,money = ? where id = ?",account.getName(),account.getMoney(),account.getId());
    }
    @Override
    public void delete(Integer id) {
        getJdbcTemplate().update("delete from account where id = ?",id);
    }
    @Override
    public void insert(Account account) {
        getJdbcTemplate().update("insert into account(name,money) values(?,?)",account.getName(),account.getMoney());
    }
    @Override
    public Integer moneyNumber(Integer money) {
        return getJdbcTemplate().queryForObject(" select count(*) from account where money > ? ", Integer.class, 900);
    }
    @Override
    public Account findByName(String name) {
        try {
            List<Account> query = getJdbcTemplate().query("select * from account where name = ?", new BeanPropertyRowMapper<Account>(Account.class), name);
            if (query.size()==1){
                return query.get(0);
            }
            else {
                return query.get(-1);
            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}

创建业务层接口

package com.spring.service;
import com.spring.beans.Account;
/**
 * 账户的业务层接口
 * @author 28985
 */
public interface IAccountService {
    /**
     *根据id查询账户
     * @param id
     * @return
     */
    Account findAccountById(Integer id);
    /**
     * 转账
     * @param sourceName 转出账户名
     * @param targetName 转入账户名称
     * @param money      转账金额
     */
    void transfer(String sourceName,String targetName,float money);
}

及业务层实现类

package com.spring.service.impl;
import com.spring.service.IAccountService;
import com.spring.beans.Account;
import com.spring.dao.IAccountDao;
/**
 * @author 28985
 */
public class AccountServiceImpl implements IAccountService {
    private IAccountDao accountDao;
    public void setAccountDao(IAccountDao accountDao) {
        this.accountDao = accountDao;
    }
    @Override
    public Account findAccountById(Integer id) {
        return accountDao.findById(id);
    }
    @Override
    public void transfer(String sourceName, String targetName, float money) {
        System.out.println("转账");
        Account sourceAccount = accountDao.findByName(sourceName);
        Account targetAccount = accountDao.findByName(targetName);
        sourceAccount.setMoney(sourceAccount.getMoney()-money);
        targetAccount.setMoney(targetAccount.getMoney()+money);
        accountDao.update(sourceAccount);
        int i= 1/0;
        accountDao.update(targetAccount);
    }
}

之后我们通过xml的方式对其进行配置

先看看不带事务的配置

<?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"
       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">
<!--    业务层-->
    <bean name="accountServiceImpl" class="com.spring.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="dao"/>
    </bean>
<!--    持久层-->
    <bean name="dao" class="com.spring.dao.impl.AccountDao">
        <property name="dataSource" ref="dataSource"/>
    </bean>
<!--    数据源-->
    <bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="username" value="root"/>
        <property name="password" value="adminadmin"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_test"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    </bean>
</beans>

编写主函数:

package com.spring.jdbcTemplate;
import com.spring.service.IAccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class JdbcTemplate_test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Bean.xml");
        IAccountService service = (IAccountService) context.getBean("accountServiceImpl");
        service.transfer("aaa","bbb",200);
    }
}

此时执行主函数,会抛出异常,异常原因是因为业务层实现类里int i= 1/0;,而且会进行错误的转账,这时我们就可以添加事务进行解决了

修改bean.xml

<?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"
       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">
<!--    业务层-->
    <bean name="accountServiceImpl" class="com.spring.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="dao"/>
    </bean>
<!--    持久层-->
    <bean name="dao" class="com.spring.dao.impl.AccountDao">
        <property name="dataSource" ref="dataSource"/>
    </bean>
<!--    数据源-->
    <bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="username" value="root"/>
        <property name="password" value="adminadmin"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_test"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    </bean>
<!--    配置事务管理器-->
    <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
<!--    配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!-- 配置事务的属性
        isolation:用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别。
        propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS。
        read-only:用于指定事务是否只读。只有查询方法才能设置为true。默认值是false,表示读写。
        timeout:用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值,以秒为单位。
        rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值。表示任何异常都回滚。
        no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值。表示任何异常都回滚。-->
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" read-only="false"/>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
        </tx:attributes>
    </tx:advice>
<!--    配置aop-->
    <aop:config>
<!--        配置切入点表达式-->
        <aop:pointcut id="pt1" expression="execution(* com.spring.service.impl.*.*(..))"/>
<!--        建立切入点表达式和事务通知的对应关系-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"/>
    </aop:config>
</beans>

即可完成事务的配置,此时运行便可以得到正常的结果

再来看看注解的配置

修改原来xml的bean.xml

主要注意第一句和最后一句的修改

<?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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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">
    <!-- 配置spring创建容器时要扫描的包-->
    <context:component-scan base-package="com.spring"></context:component-scan>
<!--    业务层-->
    <bean name="accountServiceImpl" class="com.spring.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="dao"/>
    </bean>
<!--    持久层-->
    <bean name="dao" class="com.spring.dao.impl.AccountDao">
        <property name="dataSource" ref="dataSource"/>
    </bean>
<!--    数据源-->
    <bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="username" value="root"/>
        <property name="password" value="adminadmin"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_test"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    </bean>
<!--    配置事务管理器-->
    <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 开启spring对注解事务的支持-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>

然后今天我们就只需要配置需要添加事务的类,这里专指业务层实现类AccountServiceImpl

package com.spring.service.impl;
import com.spring.service.IAccountService;
import com.spring.beans.Account;
import com.spring.dao.IAccountDao;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
 * @author 28985
 */
@Transactional
public class AccountServiceImpl implements IAccountService {
    private IAccountDao accountDao;
    public void setAccountDao(IAccountDao accountDao) {
        this.accountDao = accountDao;
    }
    @Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
    @Override
    public Account findAccountById(Integer id) {
        return accountDao.findById(id);
    }
    @Transactional(propagation = Propagation.REQUIRED,readOnly = false)
    @Override
    public void transfer(String sourceName, String targetName, float money) {
        System.out.println("转账");
        Account sourceAccount = accountDao.findByName(sourceName);
        Account targetAccount = accountDao.findByName(targetName);
        sourceAccount.setMoney(sourceAccount.getMoney()-money);
        targetAccount.setMoney(targetAccount.getMoney()+money);
        accountDao.update(sourceAccount);
//        int i= 1/0;
        accountDao.update(targetAccount);
    }
}

这时我们对比xml和注解两种配置方式

我们发现注解要针对每个方法做出不同的配置

而xml则不需要


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
0
0
0
0
分享
相关文章
微服务——SpringBoot使用归纳——为什么学习Spring Boot
本文主要探讨为什么学习Spring Boot。从Spring官方定位来看,Spring Boot旨在快速启动和运行项目,简化配置与编码。其优点包括:1) 良好的基因,继承了Spring框架的优点;2) 简化编码,通过starter依赖减少手动配置;3) 简化配置,采用Java Config方式替代繁琐的XML配置;4) 简化部署,内嵌Tomcat支持一键式启动;5) 简化监控,提供运行期性能参数获取功能。此外,从未来发展趋势看,微服务架构逐渐成为主流,而Spring Boot作为官方推荐技术,与Spring Cloud配合使用,将成为未来发展的重要方向。
99 0
微服务——SpringBoot使用归纳——为什么学习Spring Boot
Spring中事务失效的场景
因为Spring事务是基于代理来实现的,所以某个加了@Transactional的⽅法只有是被代理对象调⽤时, 那么这个注解才会⽣效 , 如果使用的是被代理对象调用, 那么@Transactional会失效 同时如果某个⽅法是private的,那么@Transactional也会失效,因为底层cglib是基于⽗⼦类来实现 的,⼦类是不能重载⽗类的private⽅法的,所以⽆法很好的利⽤代理,也会导致@Transactianal失效 如果在业务中对异常进行了捕获处理 , 出现异常后Spring框架无法感知到异常, @Transactional也会失效
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——常见问题总结
本文总结了Spring Boot中使用事务的常见问题,虽然通过`@Transactional`注解可以轻松实现事务管理,但在实际项目中仍有许多潜在坑点。文章详细分析了三个典型问题:1) 异常未被捕获导致事务未回滚,需明确指定`rollbackFor`属性;2) 异常被try-catch“吃掉”,应避免在事务方法中直接处理异常;3) 事务范围与锁范围不一致引发并发问题,建议调整锁策略以覆盖事务范围。这些问题看似简单,但一旦发生,排查难度较大,因此开发时需格外留意。最后,文章提供了课程源代码下载地址,供读者实践参考。
79 0
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——Spring Boot 事务配置
本文介绍了 Spring Boot 中的事务配置与使用方法。首先需要导入 MySQL 依赖,Spring Boot 会自动注入 `DataSourceTransactionManager`,无需额外配置即可通过 `@Transactional` 注解实现事务管理。接着通过创建一个用户插入功能的示例,展示了如何在 Service 层手动抛出异常以测试事务回滚机制。测试结果表明,数据库中未新增记录,证明事务已成功回滚。此过程简单高效,适合日常开发需求。
193 0
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——事务相关
本文介绍Spring Boot事务配置管理,阐述事务在企业应用开发中的重要性。事务确保数据操作可靠,任一异常均可回滚至初始状态,如转账、购票等场景需全流程执行成功才算完成。同时,事务管理在Spring Boot的service层广泛应用,但根据实际需求也可能存在无需事务的情况,例如独立数据插入操作。
51 0
Spring事务失效场景
本文深入探讨了Spring框架中事务管理可能失效的几种常见场景及解决方案,包括事务方法访问级别不当、方法内部自调用、错误的异常处理、事务管理器或数据源配置错误、数据库不支持事务以及不合理的事务传播行为或隔离级别。通过合理配置和正确使用`@Transactional`注解,开发者可以有效避免这些问题,确保应用的数据一致性和完整性。
113 10
【Spring】【事务】初学者直呼学会了的Spring事务入门
本文深入解析了Spring事务的核心概念与使用方法。Spring事务是一种数据库事务管理机制,通过确保操作的原子性、一致性、隔离性和持久性(ACID),维护数据完整性。文章详细讲解了声明式事务(@Transactional注解)和编程式事务(TransactionTemplate、PlatformTransactionManager)的区别与用法,并探讨了事务传播行为(如REQUIRED、REQUIRES_NEW等)及隔离级别(如READ_COMMITTED、REPEATABLE_READ)。
107 1
|
3月前
|
Spring框架的学习与应用
总的来说,Spring框架是Java开发中的一把强大的工具。通过理解其核心概念,通过实践来学习和掌握,你可以充分利用Spring框架的强大功能,提高你的开发效率和代码质量。
102 20
Spring事务相关配置、案例:转账业务追加日志及事务传播行为
Spring事务相关配置、案例:转账业务追加日志及事务传播行为
127 0
Spring高手之路24——事务类型及传播行为实战指南
本篇文章深入探讨了Spring中的事务管理,特别是事务传播行为(如REQUIRES_NEW和NESTED)的应用与区别。通过详实的示例和优化的时序图,全面解析如何在实际项目中使用这些高级事务控制技巧,以提升开发者的Spring事务管理能力。
196 1
Spring高手之路24——事务类型及传播行为实战指南

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问