SpringFramework-tx事务

事务

JdbcTemplate

spring配置文件

    <!--配置bean扫描范围-->
    <context:component-scan base-package="com.atli"></context:component-scan>

    <!--引入外部文件-->
    <context:property-placeholder location="jdbc.properties"></context:property-placeholder>

    <!--读取外部配置文件配置druid连接池-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="driverClassName" value="${jdbc.driverClassName}"></property>
        <property name="url" value="${jdbc.url}"></property>
    </bean>

    <!--创建jdbcTemplate对象,注入数据源-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="druidDataSource"></property>
    </bean>

外部配置文件

jdbc.username=root
jdbc.password=root
jdbc.url=jdbc:mysql://localhost:3306/school
jdbc.driverClassName=com.mysql.cj.jdbc.Driver

测试类

@SpringJUnitConfig(locations = "classpath:applicationcontext.xml")
public class JdbcTemplateTest {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Test
    public void testUpdate() {
        String sql = "update students set name=? where id=?";
        jdbcTemplate.update(sql,"wang",9);
    }

    @Test
    public void testInsert() {
        String sql = "insert into students(id,name,gender,age,class) values(?,?,?,?,?)";
        jdbcTemplate.update(sql,10,"zhang","女",19,"高中二班");
    }

    @Test
    public void testSelect() {
        String sql = "select * from students";
        List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
        for (Map<String, Object> map : list) {
            System.out.println(map);
        }
    }

    @Test
    public void testDelete() {
        String sql = "delete from students where id=?";
        jdbcTemplate.update(sql,9);
    }
}

RowMapper

假设有一个Emp类,该类有name和age属性且有get,set方法

这里我要使用jdbcTemplate.queryForObject(String sql,RowMapper<T> rowMapper,Object...args)来接收数据库中查询得到的单个对象(jdbcTemplate.queryForList(String sql,RowMapper<T> rowMapper)同理)

//这里采用手动封装的方式封装结果集映射即RowMapper
jdbcTemplate.queryForObject(sql,(rs,rowNum)->{
    Emp emp = new Emp();
    emp.setName(rs.getString("name"));
    emp.setAge(rs.getString("age"));
    return emp;
},1)

//这里使用RowMapper的实现类BeanPropertyRowMapper进行封装
jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<>(Emp.class),1)

//对于查询单个值(如数据条数)
jdbcTemplate.queryForObject(sql,Integer.class)

基于注解的声明式事务

spring配置文件

<!-- 配置扫描包 -->
<context:component-scan base-package="com.atli"></context:component-scan>

<!-- 配置外部配置文件(数据库连接信息) -->
<context:property-placeholder location="jdbc.properties"></context:property-placeholder>

<!-- 配置druid连接池 -->
<bean id="druidDatasource" class="com.alibaba.druid.pool.DruidDataSource">
  <property name="url" value="${jdbc.url}"></property>
  <property name="driverClassName" value="${jdbc.driverClassName}"></property>
  <property name="password" value="${jdbc.password}"></property>
  <property name="username" value="${jdbc.username}"></property>
</bean>

<!-- 配置jdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  <property name="dataSource" ref="druidDatasource"></property>
</bean>

<!-- 指定需要进行事务操作的数据源 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="druidDatasource"></property>
</bean>

<!--
  开启事务的注解驱动
  通过注解@Transactional所标识的方法或标识的类中所有的方法,都会被事务管理器管理
-->
<tx:annotation-driven transaction-manager="transactionManager" ></tx:annotation-driven>

实体类

// book类
@Component
@Data
public class Book {
    private int id;
    private String bookName;
    private int price;
    private int inventory;
}
///////////////////////////
//customer类
@Component
@Data
public class Customer {
    private int id;
    private String userName;
    private int capital;
}

Dao层

//顾客dao层接口
public interface CustomerDao {
    // 根据id查询书籍
    // 返回book对象
    public Book searchBookById(int id);
    // 根据id减少书籍库存
    // 返回该书籍库存数
    public int reduceBookInventoryById(int id);
    // 根据id减少账户中金钱
    // 返回当前账户金额
    public int reduceCapitalById(int id, int capital);
}
//////////////////////////////////////////////////////////////
//顾客dao层实现类
@Repository
public class CustomerDaoImpl implements CustomerDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public Book searchBookById(int id) {
        String sql = "select * from books where id = ?";
        Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Book.class), id);
        return book;
    }

    @Override
    public int reduceBookInventoryById(int id) {
        String sql = "update books set inventory = inventory-1 where id = ?";
        return jdbcTemplate.update(sql, id);
    }

    @Override
    public int reduceCapitalById(int id, int price) {
        String sql = "update customer set capital = capital-? where id = ?";
        return jdbcTemplate.update(sql, price, id);
    }
}

service层

// 顾客service层接口
public interface CustomerService {
    public int byBook(int bId,int uId);
}
////////////////////////////////
//顾客service层实现类
@Service
public class CustomerServiceImpl implements CustomerService {

    @Autowired
    private CustomerDaoImpl customerDaoImpl;

    @Override
    @Transactional
    public int byBook(int bId,int cId) {
        int price = customerDaoImpl.searchBookById(bId).getPrice();
        int capital = customerDaoImpl.reduceCapitalById(cId, price);
        int number =customerDaoImpl.reduceBookInventoryById(bId);
        return capital;
    }
}

controller层

@Controller
public class CustomerControllerImpl {

    @Autowired
    private CustomerServiceImpl customerServiceImpl;

    public int byBook(int bId,int cId){
        return customerServiceImpl.byBook(bId,cId);
    }
}

测试类

@SpringJUnitConfig(locations = "classpath:applicationcontext.xml")
public class customerTest {

    @Autowired
    private CustomerControllerImpl customerControllerImpl;

    @Test
    public void testByBook() {
        int capital = customerControllerImpl.byBook(1, 1);
        System.out.println(capital);
    }
}

对于@Transactional注解,可以看反编译代码来了解参数,利用这些参数可以改变事务的:只读,超时,回滚,隔离级别,传播行为等策略。

对于配置文件而言,可以替换为下面的配置类进行配置

@Configuration//配置类
@ComponentScan(basePackages = {"com.atli"})//配置包扫描路径
@EnableTransactionManagement//开启事务处理
@PropertySource("classpath:jdbc.properties")//导入外部jdbc配置文件
public class SpringConfig {

    //创建连接池
    @Bean
    public DataSource dataSource(@Value("${jdbc.username}") String username,
                                 @Value("${jdbc.password}")String password,
                                 @Value("${jdbc.url}")String url,
                                 @Value("${jdbc.driverClassName}")String driverClassName){
        //使用Java代码实例化
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driverClassName);
        return dataSource;
    }

    //配置jdbcTemplate
    @Bean(name = "jdbcTemplate")
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    //配置事务管理器
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值