创建数据库表
CREATE DATABASE IF NOT EXISTS spring CHARACTER SET utf8;
USE spring;
create table account(
id int primary key auto_increment,
username varchar(50),
money int
);
insert into account(username,money) values('jack','10000');
insert into account(username,money) values('rose','10000');
导入 jar 包
- 核心:4+1
- aop : 4 (aop联盟、spring aop、aspectj规范、spring aspect)
- 数据库:2 (jdbc/tx)
- 驱动:mysql
- 连接池:c3p0
<?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>cn.ys</groupId>
<artifactId>Spring</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- Spring 核心包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.19.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.19.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.19.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.19.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- Spring aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.19.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.19.RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
<!-- 数据库 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.19.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.19.RELEASE</version>
</dependency>
<!-- MySQL 驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Dao 层
package cn.ys.dao;
public interface AccountDao {
//扣钱
public void out(String outer,Integer money);
//进帐
public void in(String inner,Integer money);
}
package cn.ys.dao;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
public void out(String outer, Integer money) {
String sql = "update account set money = money - ? where username = ?";
getJdbcTemplate().update( sql, money, outer);
}
public void in(String inner, Integer money) {
String sql = "update account set money = money + ? where username = ?";
getJdbcTemplate().update( sql, money, inner);
}
}
Service 层
package cn.ys.service;
public interface AccountService {
/**
* 转账
* @param outer 转出帐号
* @param inner 转入帐号
* @param money 转入金额
*/
public void transfer(String outer,String inner,Integer money);
}
package cn.ys.service;
import cn.ys.dao.AccountDao;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
public class AccountServiceImpl implements AccountService {
// 由spring注入
private AccountDao accountDao;
// 提供 set 方法,让spring注入
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void transfer(String outer, String inner, Integer money) {
this.accountDao.out(outer, money);
this.accountDao.in(inner, money);
}
}
Spring 的配置
配置c3p0数据源->dao -> service
db.properties
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://yangnanxi.cn:3306/spring
user=yang
password=123456
<?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: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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 读取db.properties数据-->
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!-- 配置c3p0数据源
注:dbcp和c3po的 数据库连接的参数的属性名是不一样
please attention。。。。。
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driverClass}"/>
<property name="jdbcUrl" value="${jdbcUrl}"/>
<property name="user" value="${user}"/>
<property name="password" value="${password}"/>
</bean>
<!-- 配置dao -->
<bean id="accountDao" class="cn.ys.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置service -->
<bean id="accountService" class="cn.ys.service.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
</beans>
测试转帐
package cn.ys.spring;
import cn.ys.service.AccountService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class testSpring {
@Test
public void testSpring() {
//转帐测试
//获取Service
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
AccountService accountService = (AccountService) context.getBean("accountService");
accountService.transfer("jack","rose",100);
}
}
方式一:手动管理事务【了解】
spring 底层使用 TransactionTemplate 事务模板进行操作。
操作
1.service 需要获得 TransactionTemplate
2.spring 配置模板,并注入给service
3.模板需要注入事务管理器
4.配置事务管理器:DataSourceTransactionManager ,需要注入DataSource
了解底层即可,因为以后都是通过aop来配置事务
修改Service
package cn.ys.service;
import cn.ys.dao.AccountDao;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
public class AccountServiceImpl implements AccountService {
// 由spring注入
private AccountDao accountDao;
//Spring配置事务模版【由spring注入】
private TransactionTemplate transactionTemplate;
// 提供 set 方法,让spring注入
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
public void transfer(final String outer, final String inner, final Integer money) {
this.accountDao.out(outer, money);
this.accountDao.in(inner, money);
this.transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
//扣钱
accountDao.out( outer, money);
//int i = 10 / 0;
//进帐
accountDao.in( inner, money);
}
});
}
}
修改spring的配置文件
<?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: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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 读取db.properties数据-->
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!-- 配置c3p0数据源
注:dbcp和c3po的 数据库连接的参数的属性名是不一样
please attention。。。。。
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driverClass}"/>
<property name="jdbcUrl" value="${jdbcUrl}"/>
<property name="user" value="${user}"/>
<property name="password" value="${password}"/>
</bean>
<!-- 配置dao -->
<bean id="accountDao" class="cn.ys.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务管理器-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--配置dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务模版-->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<!--事务管理器-->
<property name="transactionManager" ref="txManager"></property>
</bean>
<!--配置service-->
<bean id="accountService" class="cn.ys.service.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
<!-- 配置事务模版-->
<property name="transactionTemplate" ref="transactionTemplate"></property>
</bean>
</beans>
方式二:工厂 bean 生成代理:半自动
Spring提供 管理事务的代理工厂bean TransactionProxyFactoryBean
修改spring配置文件
transactionAttributes:事务详情
prop.key :确定哪些方法使用当前事务配置
prop.text:用于配置事务详情
格式:PROPAGATION,ISOLATION,readOnly,-Exception,+Exception
传播行为 隔离级别 是否只读 异常回滚 异常提交
<?xml version="1.0" encoding="UTF-8"?>
<!--xmlns xml namespace:xml命名空间-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p ="http://www.springframework.org/schema/p"
xmlns:context ="http://www.springframework.org/schema/context"
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/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">
<!-- 读取db.properties数据-->
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!-- 配置c3p0数据源
注:dbcp和c3po的 数据库连接的参数的属性名是不一样
please attention。。。。。
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driverClass}"/>
<property name="jdbcUrl" value="${jdbcUrl}"/>
<property name="user" value="${user}"/>
<property name="password" value="${password}"/>
</bean>
<!-- 配置dao-->
<bean id="accountDao" class="cn.ys.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务管理器-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--配置dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置service-->
<bean id="accountService" class="cn.ys.service.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
<!-- 配置工厂代理-->
<bean id="proxyService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!--接口-->
<property name="proxyInterfaces" value="com.gyf.service.IAccountService"></property>
<!--目标对象-->
<property name="target" ref="accountService"></property>
<!--切面对象:Spring做,就不用写-->
<!-- 事务管理器-->
<property name="transactionManager" ref="txManager"/>
<!--transactionAttributes:事务属性/详情配置
key:写方法名
value写 事务配置
格式:PROPAGATION,ISOLATION,readOnly,-Exception,+Exception
传播行为 隔离级别 是否只读 异常回滚 异常提交
-->
<property name="transactionAttributes">
<props>
<prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT,+java.lang.ArithmeticException</prop>
<prop key="add">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop>
<prop key="delete">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop>
<prop key="update">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop>
<prop key="find">PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly</prop>
</props>
</property>
</bean>
</beans>