Spring----JDBC,transaction 川长思鸟来 2022-05-15 06:54 170阅读 0赞 ## JDBC模板 ## xml中配置事务管理,aop的约束 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> </beans> ![70][] 引入jar包(声明式事务管理用到aop的jar)后, 在xml中配置连接池(内置的连接池,DBCP,C3P0) 和JDBC模板 <!-- 配置Spring的jdbc模板================================================= --> <bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="DataSource"></property> </bean> <!-- 配置Spring内置连接池============================== --> <!-- <bean id="DataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 属性注入 <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql:///spring4_day03?useSSL=true&useUnicode=true&characterEncoding=UTF-8"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> --> <!-- 配置DBCP连接池=================================== --> <!-- <bean id="DataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql:///spring4_day03?useSSL=true&useUnicode=true&characterEncoding=UTF-8"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> --> <!-- 引入属性文件======================================= --> <!-- 通过context标签引入 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 配置c3p0连接池========================================== --> <bean id="DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!-- 直接写 <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql:///spring4_day03?useSSL=true&useUnicode=true&characterEncoding=UTF-8"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> --> <!-- 借用引入的属性文件 --> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> jdbc属性文件 jdbc.driverClass=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql:///spring4_day03?useSSL=true&useUnicode=true&characterEncoding=UTF-8 jdbc.username=root jdbc.password=root 使用单元测试,测试JDBC模板 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class JdbcDemo2 { @Resource(name="JdbcTemplate") private JdbcTemplate jdbcTemplate; @Test //保存操作 public void test1(){ jdbcTemplate.update("insert into account values(null,?,?)","张如花",400d); } @Test //修改操作 public void test2(){ jdbcTemplate.update("update account set name = ?,money = ? where id = ?","张如花",500d,6); } @Test //删除操作 public void test3(){ jdbcTemplate.update("delete from account where id = ?",7); } @Test //查询操作 public void test4(){ String name = jdbcTemplate.queryForObject("select name from account where id = ?",String.class,6); System.out.println(name); } @Test //统计查询 public void test5(){ Long count = jdbcTemplate.queryForObject("select count(*) from account ",Long.class); System.out.println(count); } @Test //封装到对象中 public void test6(){ Account account = jdbcTemplate.queryForObject("select *from account where id = ? ",new MyRowMapper(),6); System.out.println(account); } class MyRowMapper implements RowMapper<Account>{ @Override public Account mapRow(ResultSet rs, int rowNum) throws SQLException { Account account = new Account(rs.getInt("id"),rs.getString("name"), rs.getDouble("money")); return account; } } } class Account { private Integer id; private String name; private Double money; public Account() { } public Account(Integer id, String name, Double money) { super(); this.id = id; this.name = name; this.money = money; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Double getMoney() { return money; } public void setMoney(Double money) { this.money = money; } @Override public String toString() { return "Account [id=" + id + ", name=" + name + ", money=" + money + "]"; } } ## 事务管理 ## public interface AccountDao { public void outMoney(String from,Double money); public void inMoney(String to,Double money); } public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{ @Override public void outMoney(String from, Double money) { this.getJdbcTemplate().update("update account set money = money - ? where name = ?",money,from); } @Override public void inMoney(String to, Double money) { this.getJdbcTemplate().update("update account set money = money + ? where name = ?",money,to); } } public interface AccountService { public void transfer(String from,String to,Double money); } public class AccountServiceImpl implements AccountService { private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } @Override public void transfer( String from, String to, Double money) { accountDao.outMoney(from, money); //设置除0异常 int d = 1/0; accountDao.inMoney(to, money); } } 一个转账的实例,dao中完成对数据库的操作 dao实现类继承JdbcDaoSupport,JdbcDaoSupport源码中 ![70 1][] 只要传入一个 连接池,就会自动创建JdbcTemplate,而且JdbcDaoSupport这个类中都有相应的set方法,所以直接在xml中注入连接池就行。 <!-- 配置连接池 --> <!-- 通过context标签引入属性文件 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 配置c3p0连接池 --> <bean id="DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 配置service和dao --> <bean id="AccountDao" class="txDemo1_编程式.AccountDaoImpl"> <property name="dataSource" ref="DataSource"></property> </bean> <bean id="AccountService" class="txDemo1_编程式.AccountServiceImpl"> <property name="accountDao" ref="AccountDao"></property> </bean> 没有进行事务管理时,进行如下测试,由于AccountServiceImpl 中设置了除零异常,收账的没收到,转账的扣钱了 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:tx1.xml") public class SpringDemo1 { @Resource(name="AccountService") private AccountService accountService; @Test public void test1(){ accountService.transfer("aaa", "bbb", 700d); } ### 编程式 ### 在xml中配置事务管理器和事务管理的模板 DataSourceTransactionManager底层使用jdbc管理事务 <!-- 配置平台事务管理器==================== --> <bean id="TransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="DataSource"></property> </bean> <!-- 配置事务管理的模板 --> <bean id="TransactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="TransactionManager"></property> </bean> 在AccountServiceImpl中设置一个transactionTemplate属性,执行它的excute方法 将可能发生异常的代码写到内部类重写的方法中就可以解决问题 public class AccountServiceImpl implements AccountService { //注入dao private AccountDao accountDao; //注入事务管理的模板 private TransactionTemplate transactionTemplate; @Override public void transfer(final String from,final String to,final Double money) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus arg0) { accountDao.outMoney(from, money); int i = 1 / 0; accountDao.inMoney(to, money); } }); } public void setTransactionTemplate(TransactionTemplate transactionTemplate) { this.transactionTemplate = transactionTemplate; } public void setAccountDao(AccountDao accountDao){ this.accountDao = accountDao; } } ### 声明式 ### xml方式(aop) 配置事务管理器 <!-- 配置事务管理器 --> <bean id="TransactonManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="DataSource"></property> </bean> <!-- 配置事务的增强 --> <tx:advice id="txAdvice" transaction-manager="TransactonManager"> <tx:attributes> <tx:method name="transfer" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- aop的配置 --> <aop:config> <aop:pointcut expression="execution(* txDemo2_声明式_xml.AccountServiceImpl.*(..))" id="pointcut1"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/> </aop:config> 其中,propagation设置的是事务的传播行为 Spring中提供了七种事务的传播行为: 保证多个操作在同一个事务中 ` PROPAGATION_REQUIRED ``:默认值,如果A中有事务,使用A中的事务,如果A没有,创建一个新的事务,将操作包含进来` ` PROPAGATION_SUPPORTS ``:支持事务,如果A中有事务,使用A中的事务。如果A没有事务,不使用事务。` ` PROPAGATION_MANDATORY ``:如果A中有事务,使用A中的事务。如果A没有事务,抛出异常。` 保证多个操作不在同一个事务中 ` PROPAGATION_REQUIRES_NEW ``:如果A中有事务,将A的事务挂起(暂停),创建新事务,只包含自身操作。如果A中没有事务,创建一个新事务,包含自身操作。` ` PROPAGATION_NOT_SUPPORTED``:如果A中有事务,将A的事务挂起。不使用事务管理。` ` PROPAGATION_NEVER ``:如果A中有事务,报异常。` 嵌套式事务 ` PROPAGATION_NESTED ``:嵌套事务,如果A中有事务,按照A的事务执行,执行完成后,设置一个保存点,执行B中的操作,如果没有异常,执行通过,如果有异常,可以选择回滚到最初始位置,也可以回滚到保存点。` 注解方式 配置事务管理器 <!-- 配置事务管理器 --> <bean id="TransactonManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="DataSource"></property> </bean> 开启注解事务 <!-- 开启注解事务 --> <tx:annotation-driven transaction-manager="TransactonManager"/> 在需要目标类(AccountServiceImpl )上加一个@Transactional注解,这个注解上也可以设置传播行为等属性 @Transactional public class AccountServiceImpl implements AccountService { //注入dao private AccountDao accountDao; @Override public void transfer(String from, String to, Double money) { accountDao.outMoney(from, money); int i = 1 / 0; accountDao.inMoney(to, money); } public void setAccountDao(AccountDao accountDao){ this.accountDao = accountDao; } } [70]: /images/20220515/63a0f5d2c6f74c2299b9b245f3180c85.png [70 1]: /images/20220515/ffa00a05f9a74463889e3f21a6da4d64.png
还没有评论,来说两句吧...