黑马ssm学习笔记-Spring-day04

tech2022-07-29  169

摘要

spring中的JdbcTemplate JdbcTemplate的作用: 它就是用于和数据库交互的,实现对表的CRUD操作 如何创建该对象: 对象中的常用方法:

作业: spring基于AOP的事务控制

spring中的事务控制 基于XML的 基于注解的

project:day04_01jdbctemplate

概述和入门

导入依赖

<packaging>jar</packaging> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> </dependencies>

建立实体类domain.Account

public class Account implements Serializable { private Integer id; private String name; private Float 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 Float getMoney() { return money; } public void setMoney(Float money) { this.money = money; } @Override public String toString() { return "Account{" + "id=" + id + ", name='" + name + '\'' + ", money=" + money + '}'; } }

创建JdbcTemplateDemo1

package com.itheima.jdbctemplate; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; public class JdbcTemplateDemo1 { public static void main(String[] args) { // 准备数据源:spring的内置数据源 DriverManagerDataSource ds = new DriverManagerDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/eesy"); ds.setUsername("root"); ds.setPassword("admin"); // 1. 创建JdbcTemplate对象 JdbcTemplate jt = new JdbcTemplate(); // 给jt设置数据源 jt.setDataSource(ds); // 2. 执行操作 jt.execute("insert into account (name, money) values ('ddd', 1000)"); } }

JdbcTemplate在Spring的ioc中的使用

创建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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--配置JdbcTemplate--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!--配置数据源--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/eesy"></property> <property name="username" value="root"></property> <property name="password" value="admin"></property> </bean> </beans>

创建JdbcTemplateDemo2

package com.itheima.jdbctemplate; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; public class JdbcTemplateDemo2 { public static void main(String[] args) { // 1. 获取容器 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); // 2. 获取对象 JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class); // 3. 执行操作 jdbcTemplate.execute("insert into account (name, money) values ('fff', 1000)"); } }

CRUD

创建 JdbcTemplateDemo3

保存

package com.itheima.jdbctemplate; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; /*JdbcTemplate的CRUD操作*/ public class JdbcTemplateDemo3 { public static void main(String[] args) { // 1. 获取容器 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); // 2. 获取对象 JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class); // 3. 执行操作 // 保存 jdbcTemplate.update("insert into account (name , money) values (?, ?)", "ggg", 1000f); // 更新 // 删除 // 查询所有 // 查询一个 // 查询返回一行一列 } }

更新

package com.itheima.jdbctemplate; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; /*JdbcTemplate的CRUD操作*/ public class JdbcTemplateDemo3 { public static void main(String[] args) { // 1. 获取容器 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); // 2. 获取对象 JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class); // 3. 执行操作 // 保存 // jdbcTemplate.update("insert into account (name , money) values (?, ?)", "ggg", 1000f); // 更新 jdbcTemplate.update("update account set name=?, money=? where id=?", "test", 2000, 7); // 删除 // 查询所有 // 查询一个 // 查询返回一行一列 } }

删除

package com.itheima.jdbctemplate; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; /*JdbcTemplate的CRUD操作*/ public class JdbcTemplateDemo3 { public static void main(String[] args) { // 1. 获取容器 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); // 2. 获取对象 JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class); // 3. 执行操作 // 保存 // jdbcTemplate.update("insert into account (name , money) values (?, ?)", "ggg", 1000f); // 更新 // jdbcTemplate.update("update account set name=?, money=? where id=?", "test", 2000, 7); // 删除 jdbcTemplate.update("delete from account where id=?", 7); // 查询所有 // 查询一个 // 查询返回一行一列 } }

查询所有

package com.itheima.jdbctemplate; import com.itheima.domain.Account; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import java.util.List; /*JdbcTemplate的CRUD操作*/ public class JdbcTemplateDemo3 { public static void main(String[] args) { // 1. 获取容器 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); // 2. 获取对象 JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class); // 3. 执行操作 // 保存 // jdbcTemplate.update("insert into account (name , money) values (?, ?)", "ggg", 1000f); // 更新 // jdbcTemplate.update("update account set name=?, money=? where id=?", "test", 2000, 7); // 删除 // jdbcTemplate.update("delete from account where id=?", 7); // 查询所有 List<Account> accounts = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class)); for (Account account : accounts) { System.out.println(account); } // 查询一个 // 查询返回一行一列 } }

加上参数:

List<Account> accounts = jdbcTemplate.query("select * from account where money > ?", new BeanPropertyRowMapper<Account>(Account.class), 1000f); for (Account account : accounts) { System.out.println(account); }

查询一个

package com.itheima.jdbctemplate; import com.itheima.domain.Account; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import java.util.List; /*JdbcTemplate的CRUD操作*/ public class JdbcTemplateDemo3 { public static void main(String[] args) { // 1. 获取容器 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); // 2. 获取对象 JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class); // 3. 执行操作 // 保存 // jdbcTemplate.update("insert into account (name , money) values (?, ?)", "ggg", 1000f); // 更新 // jdbcTemplate.update("update account set name=?, money=? where id=?", "test", 2000, 7); // 删除 // jdbcTemplate.update("delete from account where id=?", 7); // 查询所有 // List<Account> accounts = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class)); /* List<Account> accounts = jdbcTemplate.query("select * from account where money > ?", new BeanPropertyRowMapper<Account>(Account.class), 1000f); for (Account account : accounts) { System.out.println(account); }*/ // 查询一个 List<Account> accounts = jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<Account>(Account.class), 1); System.out.println(accounts.isEmpty()?"没有内容":accounts.get(0)); // 查询返回一行一列 } }

查询返回一行一列

package com.itheima.jdbctemplate; import com.itheima.domain.Account; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import java.util.List; /*JdbcTemplate的CRUD操作*/ public class JdbcTemplateDemo3 { public static void main(String[] args) { // 1. 获取容器 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); // 2. 获取对象 JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class); // 3. 执行操作 // 保存 // jdbcTemplate.update("insert into account (name , money) values (?, ?)", "ggg", 1000f); // 更新 // jdbcTemplate.update("update account set name=?, money=? where id=?", "test", 2000, 7); // 删除 // jdbcTemplate.update("delete from account where id=?", 7); // 查询所有 // List<Account> accounts = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class)); /* List<Account> accounts = jdbcTemplate.query("select * from account where money > ?", new BeanPropertyRowMapper<Account>(Account.class), 1000f); for (Account account : accounts) { System.out.println(account); }*/ // 查询一个 /* List<Account> accounts = jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<Account>(Account.class), 1); System.out.println(accounts.isEmpty()?"没有内容":accounts.get(0));*/ // 查询返回一行一列 Long count = jdbcTemplate.queryForObject("select count(*) from account where money > ?", Long.class, 1000f); System.out.println(count); } }

JdbcTemplate在Dao中的应用

创建dao.IAccountDao

package com.itheima.dao; import com.itheima.domain.Account; public interface IAccountDao { /** * 根据Id查询用户 * @param accountId * @return */ Account findAccountById(Integer accountId); /** * 根据名称查询用户 * @param accountName * @return */ Account findAccountByName(String accountName); /** * 更新用户 * @param account */ void updateAccount(Account account); }

创建dao.impl.AccountDaoImpl

package com.itheima.dao.impl; import com.itheima.dao.IAccountDao; import com.itheima.domain.Account; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import java.util.List; public class AccountDaoImpl implements IAccountDao { private JdbcTemplate jdbcTemplate; public Account findAccountById(Integer accountId) { List<Account> accounts = jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<Account>(Account.class), accountId); return accounts.isEmpty()?null:accounts.get(0); } public Account findAccountByName(String accountName) { List<Account> accounts = jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<Account>(Account.class), accountName); if (accounts.isEmpty()) return null; if (accounts.size() > 1) throw new RuntimeException("结果集不唯一"); return accounts.get(0); } public void updateAccount(Account account) { jdbcTemplate.update("update account set name = ?, money = ? where id = ?", account.getName(), account.getMoney(), account.getId()); } }

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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--配置账户的持久层--> <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <!--配置JdbcTemplate--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!--配置数据源--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/eesy"></property> <property name="username" value="root"></property> <property name="password" value="admin"></property> </bean> </beans>

创建JdbcTemplateDemo4测试

package com.itheima.jdbctemplate; import com.itheima.dao.IAccountDao; import com.itheima.domain.Account; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; /*JdbcTemplate的CRUD操作*/ public class JdbcTemplateDemo4 { public static void main(String[] args) { // 1. 获取容器 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); // 2. 获取对象 IAccountDao accountDao = ac.getBean("accountDao", IAccountDao.class); Account account = accountDao.findAccountById(1); System.out.println(account); account.setMoney(10000f); accountDao.updateAccount(account); } }

创建JdbcDaoSupport抽取Dao中重复代码

package com.itheima.dao.impl; import org.springframework.jdbc.core.JdbcTemplate; import javax.sql.DataSource; public class JdbcDaoSupport { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public JdbcTemplate getJdbcTemplate() { return jdbcTemplate; } public void setDataSource(DataSource dataSource) { if (jdbcTemplate == null) jdbcTemplate = createJdbcTemplate(dataSource); } private JdbcTemplate createJdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } }

在AccountDaoImpl中继承

package com.itheima.dao.impl; import com.itheima.dao.IAccountDao; import com.itheima.domain.Account; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import java.util.List; public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao { public Account findAccountById(Integer accountId) { List<Account> accounts = super.getJdbcTemplate().query("select * from account where id = ?", new BeanPropertyRowMapper<Account>(Account.class), accountId); return accounts.isEmpty()?null:accounts.get(0); } public Account findAccountByName(String accountName) { List<Account> accounts = super.getJdbcTemplate().query("select * from account where name = ?", new BeanPropertyRowMapper<Account>(Account.class), accountName); if (accounts.isEmpty()) return null; if (accounts.size() > 1) throw new RuntimeException("结果集不唯一"); return accounts.get(0); } public void updateAccount(Account account) { super.getJdbcTemplate().update("update account set name = ?, money = ? where id = ?", account.getName(), account.getMoney(), account.getId()); } }

在bean.xml中注入dataSource

<?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 id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"> <!-- <property name="jdbcTemplate" ref="jdbcTemplate"></property>--> <property name="dataSource" ref="dataSource"></property> </bean> <!--配置JdbcTemplate--> <!-- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">--> <!-- <property name="dataSource" ref="dataSource"></property>--> <!-- </bean>--> <!--配置数据源--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/eesy"></property> <property name="username" value="root"></property> <property name="password" value="admin"></property> </bean> </beans>

JdbcSupport在Spring中已存在

只需要在AccountDaoImpl中导入即可:

使用继承后,不能用注解配置了。

project:day04_02account_aoptx_xml

基于XML的AOP事务控制

复制day03_01Account

删除factory包

修改bean.xml

修改aop的xml头部信息:

配置aop

<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--配置Service--> <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> <!--注入dao--> <property name="accountDao" ref="accountDao"></property> </bean> <!--配置Dao对象--> <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"> <!--注入QueryRunner--> <property name="runner" ref="runner"></property> <!--注入ConnectionUtils--> <property name="connectionUtils" ref="connectionUtils"></property> </bean> <!--配置QueryRunner--> <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"></bean> <!-- 配置数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!--连接数据库的必备信息--> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/eesy"></property> <property name="user" value="root"></property> <property name="password" value="admin"></property> </bean> <!-- 配置Connection的工具类 ConnectionUtils --> <bean id="connectionUtils" class="com.itheima.utils.ConnectionUtils"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 配置事务管理器--> <bean id="txManager" class="com.itheima.utils.TransactionManager"> <property name="connectionUtils" ref="connectionUtils"></property> </bean> <!--配置aop--> <aop:config> <!--配置通用切入点表达式--> <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"></aop:pointcut> <aop:aspect id="txAdvice" ref="txManager"> <!--配置前置通知:开启事务--> <aop:before method="beginTransaction" pointcut-ref="pt1"></aop:before> <!--配置后置通知:提交事务--> <aop:after-returning method="commit" pointcut-ref="pt1"></aop:after-returning> <!--配置异常通知:回滚事务--> <aop:after-throwing method="rollback" pointcut-ref="pt1"></aop:after-throwing> <!--配置最终通知:释放连接--> <aop:after method="release" pointcut-ref="pt1"></aop:after> </aop:aspect> </aop:config> </beans>

project:day04_03account_aoptx_anno

基于注解的AOP事务控制

复制day04_02account_aoptx_xml

改造ioc,修改bean.xml

1. 导入context

2. 配置spring创建容器时要扫描的包

<!--配置spring创建容器时要扫描的包--> <context:component-scan base-package="com.itheima"></context:component-scan>

3. 配置Service

4. 配置Dao

5. 配置Connection的工具类 ConnectionUtils

6. 配置事务管理器、配置aop

package com.itheima.utils; import org.aspectj.lang.annotation.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.sql.SQLException; @Component("txManager") @Aspect public class TransactionManager { @Autowired private ConnectionUtils connectionUtils; @Pointcut("execution( * com.itheima.service.impl.*.*(..))") public void pt1(){}; @Before("pt1()") public void beginTransaction() { try { connectionUtils.getThreadConnection().setAutoCommit(false); } catch (Exception e) { throw new RuntimeException(e); } } @AfterReturning("pt1()") public void commit() { try { connectionUtils.getThreadConnection().commit(); } catch (Exception e) { throw new RuntimeException(e); } } @AfterThrowing("pt1()") public void rollback() { try { connectionUtils.getThreadConnection().rollback(); } catch (Exception e) { throw new RuntimeException(e); } } @After("pt1()") public void release() { try { connectionUtils.getThreadConnection().close(); connectionUtils.removeConnection(); } catch (Exception e) { throw new RuntimeException(e); } } }

7. 开启spring对注解AOP的支持

<!--开启spring对注解AOP的支持--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

8. 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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.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.itheima"></context:component-scan> <!--配置QueryRunner--> <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"></bean> <!-- 配置数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!--连接数据库的必备信息--> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/eesy"></property> <property name="user" value="root"></property> <property name="password" value="admin"></property> </bean> <!--开启spring对注解AOP的支持--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>

执行测试类产生异常

是因为最终通知和异常通知的顺序有问题。 只能使用环绕通知

使用环绕通知

@Around("pt1()") public Object aroundAdvice(ProceedingJoinPoint pjp){ Object rtValue = null; try { //1.获取参数 Object[] args = pjp.getArgs(); //2.开启事务 this.beginTransaction(); //3.执行方法 rtValue = pjp.proceed(args); //4.提交事务 this.commit(); //返回结果 return rtValue; }catch (Throwable e){ //5.回滚事务 this.rollback(); throw new RuntimeException(e); }finally { //6.释放资源 this.release(); } }

project:day04_04tx

Spring事务控制

1. 配置依赖

<?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>com.itheima</groupId> <artifactId>day04_04tx</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.7</version> </dependency> </dependencies> </project>

2. 拷贝day04_01jdbctemplate

删除 AccountDaoImpl2 JdbcDaoSupport.java

3. 创建IAccountService

4. 创建AccountServiceImpl

package com.itheima.service.impl; import com.itheima.dao.IAccountDao; import com.itheima.domain.Account; import com.itheima.service.IAccountService; import org.springframework.stereotype.Service; /** * 账户的业务层实现类 * * 事务控制应该都是在业务层 */ public class AccountServiceImpl implements IAccountService{ private IAccountDao accountDao; public void setAccountDao(IAccountDao accountDao) { this.accountDao = accountDao; } @Override public Account findAccountById(Integer accountId) { return accountDao.findAccountById(accountId); } @Override public void transfer(String sourceName, String targetName, Float money) { System.out.println("transfer...."); //2.1根据名称查询转出账户 Account source = accountDao.findAccountByName(sourceName); //2.2根据名称查询转入账户 Account target = accountDao.findAccountByName(targetName); //2.3转出账户减钱 source.setMoney(source.getMoney()-money); //2.4转入账户加钱 target.setMoney(target.getMoney()+money); //2.5更新转出账户 accountDao.updateAccount(source); int i=1/0; //2.6更新转入账户 accountDao.updateAccount(target); } }

5. 创建AccountServiceTest

package com.itheima.test; import com.itheima.service.IAccountService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * 使用Junit单元测试:测试我们的配置 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:bean.xml") public class AccountServiceTest { @Autowired private IAccountService as; @Test public void testTransfer(){ as.transfer("aaa","bbb",100f); } }

pom.xml需导入:

<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.2.RELEASE</version> </dependency>

6. 配置业务层

<!--配置业务层--> <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"></property> </bean>

此时无法实现事务控制

project:day04_05tx_xml

拷贝day04_04tx

基于xml的Spring事务管理

spring中基于XML的声明式事务控制配置步骤 1、配置事务管理器 2、配置事务的通知 此时我们需要导入事务的约束 tx名称空间和约束,同时也需要aop的 使用tx:advice标签配置事务通知 属性: id:给事务通知起一个唯一标识 transaction-manager:给事务通知提供一个事务管理器引用 3、配置AOP中的通用切入点表达式 4、建立事务通知和切入点表达式的对应关系 5、配置事务的属性 是在事务的通知tx:advice标签的内部

1. 配置事务管理器

<!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property>

2. 配置事务的通知

导入事务的约束 tx名称空间和约束,同时也需要aop的

<!--配置事务的通知--> <tx:advice id="txAdvice" transaction-manager="transactionManager"></tx:advice>

3. 配置AOP中的通用切入点表达式

<!--配置aop--> <aop:config> <!--配置切入点表达式--> <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"/> </aop:config>

4. 建立事务通知和切入点表达式的对应关系

<!--配置aop--> <aop:config> <!--配置切入点表达式--> <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"/> <!--建立事务通知和切入点表达式的对应关系--> <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor> </aop:config>

5. 配置事务的属性

<!-- 配置事务的通知--> <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:method> </tx:attributes> </tx:advice>

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 id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"></property> </bean> <!--配置账户的持久层--> <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"> <property name="dataSource" ref="dataSource"></property> </bean> <!--配置数据源--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/eesy"></property> <property name="username" value="root"></property> <property name="password" value="admin"></property> </bean> <!-- spring中基于XML的声明式事务控制配置步骤 1、配置事务管理器 2、配置事务的通知 此时我们需要导入事务的约束 tx名称空间和约束,同时也需要aop的 使用tx:advice标签配置事务通知 属性: id:给事务通知起一个唯一标识 transaction-manager:给事务通知提供一个事务管理器引用 3、配置AOP中的通用切入点表达式 4、建立事务通知和切入点表达式的对应关系 5、配置事务的属性 是在事务的通知tx:advice标签的内部 --> <!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </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:method> </tx:attributes> </tx:advice> <!--配置aop--> <aop:config> <!--配置切入点表达式--> <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"/> <!--建立事务通知和切入点表达式的对应关系--> <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor> </aop:config> </beans>

6. 测试

project:day04_06tx_anno

拷贝day04_05tx_xml

基于注解的Spring事务管理

修改bean.xml

导入context

配置业务层accountService

配置账户的持久层accountDao

配置JdbcTemplate

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

配置spring创建容器时要扫描的包

<!-- 配置spring创建容器时要扫描的包--> <context:component-scan base-package="com.itheima"></context:component-scan>

步骤

spring中基于注解 的声明式事务控制配置步骤 1、配置事务管理器 2、开启spring对注解事务的支持 3、在需要事务支持的地方使用@Transactional注解

配置事务管理器

<!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean>

开启spring对注解事务的支持

<!--开启spring对注解事务的支持--> <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

在需要事务支持的地方使用@Transactional注解

project:day04_07anno_tx_withoutxml

1. SpringConfiguration

package config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.PropertySource; import org.springframework.transaction.annotation.EnableTransactionManagement; /** * spring的配置类,相当于bean.xml */ @Configuration @ComponentScan("com.itheima") @Import({JdbcConfig.class,TransactionConfig.class}) @PropertySource("jdbcConfig.properties") @EnableTransactionManagement public class SpringConfiguration { }

2. JdbcConfig

package config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; import javax.sql.DataSource; /** * 和连接数据库相关的配置类 */ 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; /** * 创建JdbcTemplate * @param dataSource * @return */ @Bean(name="jdbcTemplate") public JdbcTemplate createJdbcTemplate(DataSource dataSource){ return new JdbcTemplate(dataSource); } /** * 创建数据源对象 * @return */ @Bean(name="dataSource") public DataSource createDataSource(){ DriverManagerDataSource ds = new DriverManagerDataSource(); ds.setDriverClassName(driver); ds.setUrl(url); ds.setUsername(username); ds.setPassword(password); return ds; } }

2. 创建jdbcConfig.properties

jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/eesy jdbc.username=root jdbc.password=1234

3. 创建TransactionConfig.java

package config; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; /** * 和事务相关的配置类 */ public class TransactionConfig { /** * 用于创建事务管理器对象 * @param dataSource * @return */ @Bean(name="transactionManager") public PlatformTransactionManager createTransactionManager(DataSource dataSource){ return new DataSourceTransactionManager(dataSource); } }

4. 测试

package com.itheima.test; import com.itheima.service.IAccountService; import config.SpringConfiguration; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * 使用Junit单元测试:测试我们的配置 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes= SpringConfiguration.class) public class AccountServiceTest { @Autowired private IAccountService as; @Test public void testTransfer(){ as.transfer("aaa","bbb",100f); } }
最新回复(0)