事务
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);
}
}