一.注解小结
其中aop未使用,可能会提示。xml文件配置如下:
基本语法:<context:component-scan base-package=”pagkage1[,pagkage2,…,pagkageN]”/>
<?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-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 指定需要扫描的包,使注解生效 -->
<context:component-scan base-package="cn.testSpring" />
<!-- 启动基于注解的声明式AspectJ支持 -->
<aop:aspectj-autoproxy />
</beans>
1.Bean的实例化
@Component
@Component是所有受Spring管理组件的通用形式,@Component注解可以放在所有的类的头上,@Component不推荐使用。@Component("UserComponent")或者@Component(value="user") // 类似于<bean id="user" class="..." />
@Controller
@Controller对应表现层的Bean,也就是Action。@Controller("UserAction")
@Service
@Service对应service层的Bean。@Service("UserService")
@Repository
@Respository对应数据库访问层Bean。@Repository("userDao")
@Configuration把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。@Service用于标注业务层组件、
@Controller用于标注控制层组件(如struts中的action)
@Repository用于标注数据访问组件,即DAO组件。
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
@Scope用于指定scope作用域的(用在类上)
@PostConstruct用于指定初始化方法(用在方法上)
@PreDestory用于指定销毁方法(用在方法上)
@DependsOn:定义Bean初始化及销毁时的顺序
@Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
@Autowired 默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。如下:
@Autowired @Qualifier("personDaoBean") 存在多个实例配合使用
@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。
具体例子可以参见:https://blog.csdn.net/achenyuan/article/details/72786759
二.Spring JDBC
springjdbc是springDao层的基础,主要有四个包,core、DataSource(访问数据的工具类)、Object(以面向对象的方式访问数据库)、support,可以支持下述:
- JDBC : org.springframework.jdbc.core.JdbcTemplate
- MyBatis : org.springframework.orm.ibatis.SqlMapClientTemplate
引入相应jar包:
- spring-tx-XXX-RELEASE.jar
- spring-jdbc-XXX-.RELEASE.jar
- mysql驱动.
JdbcTemplate是spring JDBC 的核心类,继承了JdbcAccessory抽象类,同时实现了JdbcOperations接口,具有以下几个接口:
- DataSource(获取数据库连接,还可实现缓冲池、分布式事务)
- SQL Exception Translator(异常处理)
Spring数据源
常用的有下面三种:
- Spring 数据源实现类 DriverManagerDataSource
- DBCP 数据源 BasicDataSource
- C3P0 数据源 ComboPooledDataSource
需要使用不同的数据源时,方法很简单(之前需要导入相应的包),只需要将DataSource后面的class路径设置为相应的即可:
(1)DBCP连接池(导包)
com.springsource.org.apache.commons.dbcp-XXX.osgi.jar
com.springsource.org.apache.commons.pool-XXX.jar
org.apache.commons.dbcp.BasicDataSource
(2)默认连接池
org.springframework.jdbc.datasource.DriverManagerDataSource
(3)C3P0连接池
com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
com.mchange.v2.c3p0.ComboPooledDataSource
Spring源文件配置
配置文件有两类配置方法,第一种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-4.3.xsd">
<!-- 1配置数据源(比较类似于jdbc的配置文件) -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--数据库驱动 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<!--连接数据库的url -->
<property name="url" value="jdbc:mysql://localhost:3306/spring" />
<!--连接数据库的用户名 -->
<property name="username" value="*****" />
<!--连接数据库的密码 -->
<property name="password" value="*****" />
</bean>
<!-- 2配置JDBC模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 默认必须使用数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!--定义id为accountDao的Bean-->
<bean id="accountDao" class="cn.testSpringJdbc.impl.AccountDaoImpl">
<!-- 将jdbcTemplate注入到accountDao实例中 -->
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
</beans>
第二种多文件配置如下:先配置jdbc.properties,再配置dataSource,最后注入实例
jdbc.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/sso_application
username=root
password=minlay294716
jdbcPoolInitSize=5
<!-- 导入资源文件的两种方法 -->
1.<context:property-placeholder location="classpath:jdbc.properties"/>
2.<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties"></property>
</bean><!-- 配置数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
<property name="jdbcUrl" value="${jdbcUrl}"></property>
<property name="driverClass" value="${driverClass}"></property>
<property name="initialPoolSize" value="${initPoolSize}"></property>
<property name="maxPoolSize" value="${maxPoolSize}"></property> </bean>
<!-- 配置 spring 的 JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="accountDao" class="cn.testSpringJdbc.impl.AccountDaoImpl">
<!-- 将jdbcTemplate注入到accountDao实例中 -->
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
JDBCTemplate详解
JdbcTemplate主要提供以下五类方法:
execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句(DML数据操纵语言命令使用户能够查询数据库以及操作已有数据库中的数据;DDL语句用语定义和管理数据库中的对象,如Create,Alter和Drop.);
update方法及batchUpdate方法:update方法用于执行增、改、删等语句;batchUpdate方法用于执行批处理相关语句;
query方法及queryForXXX方法:用于执行查询相关语句;
call方法:用于执行存储过程、函数相关语句。
基本增删改操作
- 插入操作
- String sql = “insert into customers values(?)”;
- jdbcTemplate.update(sql, “哈哈”);
- 修改操作
- String sql = “update customers set name= ? where id =?”;
- jdbcTemplate.update(sql, “minlay”, 3);
- 删除操作
- String sql = “delete from customers where id =?”;
- jdbcTemplate.update(sql, 1);
查询操作
简单查询:
String name = jdbcTemplate.queryForObject(sql, String.class, 2);
String sql = “select name from customers where id = ?”;
int count = jdbcTemplate.queryForInt(sql);
String sql = “select count(*) from customers”;
@Test
public void executeTest() {
// 加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取JdbcTemplate实例
JdbcTemplate jdTemplate = (JdbcTemplate) applicationContext.getBean("jdbcTemplate");
// 使用execute()方法执行SQL语句,创建用户账户管理表account
jdTemplate.execute("create table account(" +
"id int primary key auto_increment," +
"username varchar(50)," +
"balance double)");
System.out.println("账户表account创建成功!");
}
(2)update()
用一个账户管理案例来作为实例:
组织结构如图所示:
package cn.testSpringJdbc.beans;
public class Account {
private Integer id; // 账户id
private String username; // 用户名
private Double balance; // 账户余额
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Double getBalance() {
return balance;
}
public void setBalance(Double balance) {
this.balance = balance;
}
public String toString() {
return "Account [id=" + id + ", "
+ "username=" + username +
", balance=" + balance + "]";
}
}
package cn.testSpringJdbc.dao;
import java.util.List;
import cn.testSpringJdbc.beans.Account;
public interface AccountDao {
// 添加
public int addAccount(Account account);
// 更新
public int updateAccount(Account account);
// 删除
public int deleteAccount(int id);
// 通过id查询
public Account findAccountById(int id);
// 查询所有账户
public List<Account> findAllAccount();
}
package cn.testSpringJdbc.dao.impl;
import java.util.List;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import cn.testSpringJdbc.beans.Account;
import cn.testSpringJdbc.dao.AccountDao;
public class AccountDaoImpl implements AccountDao {
// 声明JdbcTemplate属性及其setter方法
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
// 添加账户
public int addAccount(Account account) {
// 定义SQL
String sql = "insert into account(username,balance) value(?,?)";
// 定义数组来存放SQL语句中的参数
Object[] obj = new Object[] {
account.getUsername(),
account.getBalance()
};
// 执行添加操作,返回的是受SQL语句影响的记录条数
int num = this.jdbcTemplate.update(sql, obj);
return num;
}
// 更新账户
public int updateAccount(Account account) {
// 定义SQL
String sql = "update account set username=?,balance=? where id = ?";
// 定义数组来存放SQL语句中的参数
Object[] params = new Object[] {
account.getUsername(),
account.getBalance(),
account.getId()
};
// 执行添加操作,返回的是受SQL语句影响的记录条数
int num = this.jdbcTemplate.update(sql, params);
return num;
}
// 删除账户
public int deleteAccount(int id) {
// 定义SQL
String sql = "delete from account where id = ? ";
// 执行添加操作,返回的是受SQL语句影响的记录条数
int num = this.jdbcTemplate.update(sql, id);
return num;
}
// 通过id查询账户数据信息
public Account findAccountById(int id) {
//定义SQL语句
String sql = "select * from account where id = ?";
// 创建一个新的BeanPropertyRowMapper对象
RowMapper<Account> rowMapper = new BeanPropertyRowMapper<Account>(Account.class);
// 将id绑定到SQL语句中,并通过RowMapper返回一个Object类型的单行记录
Account account = null;
try {
account = this.jdbcTemplate.queryForObject(sql, rowMapper, id);;
} catch (EmptyResultDataAccessException e) {
return null;
}
return account;
}
// 查询所有账户信息
public List<Account> findAllAccount() {
// 定义SQL语句
String sql = "select * from account";
// 创建一个新的BeanPropertyRowMapper对象
RowMapper<Account> rowMapper =
new BeanPropertyRowMapper<Account>(Account.class);
// 执行静态的SQL查询,并通过RowMapper返回结果
return this.jdbcTemplate.query(sql, rowMapper);
}
}
package cn.testSpringJdbc.junitTest;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import cn.testSpringJdbc.beans.Account;
import cn.testSpringJdbc.dao.AccountDao;
public class JdbcTemplateTest {
@Test
public void executeTest() {
// 加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取JdbcTemplate实例
JdbcTemplate jdTemplate = (JdbcTemplate) applicationContext.getBean("jdbcTemplate");
// 使用execute()方法执行SQL语句,创建用户账户管理表account
jdTemplate.execute("create table account(" +
"id int primary key auto_increment," +
"username varchar(50)," +
"balance double)");
System.out.println("账户表account创建成功!");
}
@Test
public void addAccountTest() {
// 加载配置文件
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取AccountDao实例
AccountDao accountDao =
(AccountDao) applicationContext.getBean("accountDao");
// 创建Account对象,并向Account对象中添加数据
Account account = new Account();
account.setUsername("tom");
account.setBalance(1000.00);
// 执行addAccount()方法,并获取返回结果
int num = accountDao.addAccount(account);
if (num > 0) {
System.out.println("成功插入了" + num + "条数据!");
} else {
System.out.println("插入操作执行失败!");
}
}
@Test
public void updateAccountTest() {
// 加载配置文件
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取AccountDao实例
AccountDao accountDao =
(AccountDao) applicationContext.getBean("accountDao");
// 创建Account对象,并向Account对象中添加数据
Account account = new Account();
account.setId(1);
account.setUsername("tom");
account.setBalance(2000.00);
// 执行updateAccount()方法,并获取返回结果
int num = accountDao.updateAccount(account);
if (num > 0) {
System.out.println("成功修改了" + num + "条数据!");
} else {
System.out.println("修改操作执行失败!");
}
}
@Test
public void deleteAccountTest() {
// 加载配置文件
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取AccountDao实例
AccountDao accountDao =
(AccountDao) applicationContext.getBean("accountDao");
// 执行deleteAccount()方法,并获取返回结果
int num = accountDao.deleteAccount(1);
if (num > 0) {
System.out.println("成功删除了" + num + "条数据!");
} else {
System.out.println("删除操作执行失败!");
}
}
@Test
public void findAccountByIdTest() {
// 加载配置文件
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取AccountDao实例
AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
// 执行findAccountById()方法
Account account = accountDao.findAccountById(1);
if(account==null) {
System.out.println("没有该用户");
}else {
System.out.println(account);
}
}
@Test
public void findAllAccountTest() {
// 加载配置文件
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取AccountDao实例
AccountDao accountDao =
(AccountDao) applicationContext.getBean("accountDao");
// 执行findAllAccount()方法,获取Account对象的集合
List<Account> account = accountDao.findAllAccount();
// 循环输出集合中的对象
for (Account act : account) {
System.out.println(act);
}
}
}
高级使用参见:https://blog.csdn.net/dyllove98/article/details/7772463
三.Spring事务管理
PlatformTransactionManager:平台事务管理器.
- commit(TransactionStatus status)用于提交事务
- getTransaction(TransactionDefinition definition)获取事物状态信息,根据definition返回TransactionStatus
- rollback(TransactionStatus status)
- Spring为不同的持久化框架提供了不同PlatformTransactionManager接口实现 org.springframework.jdbc.datasource.DataSourceTransactionManager : 使用Spring JDBC或 iBatis进行持久化数据时使用org.springframework.orm.hibernate5.HibernateTransactionManager : 使用Hibernate5.0版本进行持久化数据时使用org.springframework.transaction.jta.JtaTransactionManager 使用一个JTA实现来管理事务,在一个事务跨越多个资源时必须使用
TransactionDefinition接口是定义事务的对象,对象重定义了事务规则,并提供了下列方法来获取事务相关信息:
- String getName():获取事务对象名称
- int getIsolationLevel():获取事务隔离级别
- int getPropagationBehavior():获取事务的传播行为
- int getTimeout():获取事务的超时时间
- Boolean isReadyOnly():获取事务是否只读
TransactionStatus:事务具体运行状态
事务管理方式
编程式事务管理:是通过编写代码实现的事务管理,包括定义事务的开始、正常执行后的事务提交、异常时的事务回滚。
声明式事务管理:通过AOP技术实现的事务管理。主要思想是将事务作为一个切面,然后通过AOP将其织入业务目标类。
(1)编程式事务管理
这种方式太麻烦,基本不用编写事务处理类,service层的实现,并完成配置:
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
public void out(String from, Double money) {
String sql = "update account set money = money - ? where name = ?";
this.getJdbcTemplate().update(sql, money,from);
}
public void in(String to, Double money) {
String sql = "update account set money = money + ? where name = ?";
this.getJdbcTemplate().update(sql, money , to);
}
}
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void transfer(final String from, final String to, final Double money) {
accountDao.out(from, money);
int d = 1 / 0;
accountDao.in(to, money);
}
}
<!-- 业务层类 -->
<bean id="accountService" class="cn.testspring.AccountServiceImpl">
<!-- 在业务层注入Dao -->
<property name="accountDao" ref="accountDao"/>
<!-- 在业务层注入事务的管理模板 -->
<property name="transactionTemplate" ref="transactionTemplate"/>
</bean>
<!-- 持久层类 -->
<bean id="accountDao" class="cn.testspring.AccountDaoImpl">
<!-- 注入连接池的对象,通过连接池对象创建模板. -->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 事务管理的模板 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 需要注入连接池,通过连接池获得连接 -->
<property name="dataSource" ref="dataSource"/>
</bean>
A:注册事务管理器
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 需要注入连接池,通过连接池获得连接 -->
<property name="dataSource" ref="dataSource"/>
</bean>
B:注册事务模板类
<!-- 事务管理的模板 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
C:模板类管理事务
<!-- 业务层类 -->
<bean id="accountService" class="cn.testSpring.AccountServiceImpl">
<!-- 在业务层注入Dao -->
<property name="accountDao" ref="accountDao"/>
<!-- 在业务层注入事务的管理模板 -->
<property name="transactionTemplate" ref="transactionTemplate"/>
</bean>
D:业务层套用模板
public void transfer(final String from, final String to, final Double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
accountDao.out(from, money);
int d = 1 / 0;
accountDao.in(to, money);
}
}
}
(2)声明式事务管理
A.基于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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!-- 1.配置数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--数据库驱动 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<!--连接数据库的url -->
<property name="url" value="jdbc:mysql://localhost/spring" />
<!--连接数据库的用户名 -->
<property name="username" value="root" />
<!--连接数据库的密码 -->
<property name="password" value="minlay294716" />
</bean>
<!-- 2.配置JDBC模板 -->
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 默认必须使用数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!--3.定义id为accountDao的Bean -->
<bean id="accountDao" class="cn.testSpringTransaction.AccountDaoImpl">
<!-- 将jdbcTemplate注入到AccountDao实例中 -->
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<!-- 4.事务管理器,依赖于数据源 -->
<bean id="transactionManager" class= "org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 5.编写通知:对事务进行增强(通知),需要编写对切入点和具体执行事务细节 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- name:*表示任意方法名称 -->
<tx:method name="*" propagation="REQUIRED"
isolation="DEFAULT" read-only="false" />
</tx:attributes>
</tx:advice>
<!-- 6.编写aop,让spring自动对目标生成代理,需要使用AspectJ的表达式 -->
<aop:config>
<!-- 切入点 -->
<aop:pointcut expression="execution(* cn.testSpringTransaction.*.*(..))"
id="txPointCut" />
<!-- 切面:将切入点与通知整合 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut" />
</aop:config>
</beans>
B.基于注解方式
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!-- 1.配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--数据库驱动 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<!--连接数据库的url -->
<property name="url" value="jdbc:mysql://localhost/spring" />
<!--连接数据库的用户名 -->
<property name="username" value="root" />
<!--连接数据库的密码 -->
<property name="password" value="minlay294716" />
</bean>
<!-- 2.配置JDBC模板 -->
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 默认必须使用数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!--3.定义id为accountDao的Bean -->
<bean id="accountDao" class="cn.testSpringTransaction.AccountDaoImpl">
<!-- 将jdbcTemplate注入到AccountDao实例中 -->
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<!-- 4.事务管理器,依赖于数据源 -->
<bean id="transactionManager" class=
"org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 5.注册事务管理器驱动 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
在转账函数上加入下注解:
@Transactional(propagation = Propagation.REQUIRED,
isolation = Isolation.DEFAULT, readOnly = false)
到此,spring的所有基础内容完了,下阶段可以学习web层的spring MVC ,限于本人水平,文中难免会存在错误,希望大家批评指正。
备注:事务处理的代码,请大家自己看。
package cn.testSpringTransaction;
public class Account {
private Integer id; // 账户id
private String username; // 用户名
private Double balance; // 账户余额
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Double getBalance() {
return balance;
}
public void setBalance(Double balance) {
this.balance = balance;
}
public String toString() {
return "Account [id=" + id + ", "
+ "username=" + username +
", balance=" + balance + "]";
}
}
package cn.testSpringTransaction;
import java.util.List;
public interface AccountDao {
// 添加
public int addAccount(Account account);
// 更新
public int updateAccount(Account account);
// 删除
public int deleteAccount(int id);
// 通过id查询
public Account findAccountById(int id);
// 查询所有账户
public List<Account> findAllAccount();
// 转账
public void transfer(String outUser,String inUser,Double money);
}
package cn.testSpringTransaction;
import java.util.List;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
public class AccountDaoImpl implements AccountDao {
// 声明JdbcTemplate属性及其setter方法
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
// 添加账户
public int addAccount(Account account) {
// 定义SQL
String sql = "insert into account(username,balance) value(?,?)";
// 定义数组来存放SQL语句中的参数
Object[] obj = new Object[] { account.getUsername(), account.getBalance() };
// 执行添加操作,返回的是受SQL语句影响的记录条数
int num = this.jdbcTemplate.update(sql, obj);
return num;
}
// 更新账户
public int updateAccount(Account account) {
// 定义SQL
String sql = "update account set username=?,balance=? where id = ?";
// 定义数组来存放SQL语句中的参数
Object[] params = new Object[] { account.getUsername(), account.getBalance(), account.getId() };
// 执行添加操作,返回的是受SQL语句影响的记录条数
int num = this.jdbcTemplate.update(sql, params);
return num;
}
// 删除账户
public int deleteAccount(int id) {
// 定义SQL
String sql = "delete from account where id = ? ";
// 执行添加操作,返回的是受SQL语句影响的记录条数
int num = this.jdbcTemplate.update(sql, id);
return num;
}
// 通过id查询账户数据信息
public Account findAccountById(int id) {
// 定义SQL语句
String sql = "select * from account where id = ?";
// 创建一个新的BeanPropertyRowMapper对象
RowMapper<Account> rowMapper = new BeanPropertyRowMapper<Account>(Account.class);
// 将id绑定到SQL语句中,并通过RowMapper返回一个Object类型的单行记录
return this.jdbcTemplate.queryForObject(sql, rowMapper, id);
}
// 查询所有账户信息
public List<Account> findAllAccount() {
// 定义SQL语句
String sql = "select * from account";
// 创建一个新的BeanPropertyRowMapper对象
RowMapper<Account> rowMapper = new BeanPropertyRowMapper<Account>(Account.class);
// 执行静态的SQL查询,并通过RowMapper返回结果
return this.jdbcTemplate.query(sql, rowMapper);
}
/**
* 转账
* inUser:收款人
* outUser:汇款人
* money:收款金额
*/
@Transactional(propagation = Propagation.REQUIRED,
isolation = Isolation.DEFAULT, readOnly = false)
public void transfer(String outUser, String inUser, Double money) {
// 收款时,收款用户的余额=现有余额+所汇金额
this.jdbcTemplate.update("update account set balance = balance +? "
+ "where username = ?",money, inUser);
// 模拟系统运行时的突发性问题
//int i = 1/0;
// 汇款时,汇款用户的余额=现有余额-所汇金额
this.jdbcTemplate.update("update account set balance = balance-? "
+ "where username = ?",money, outUser);
}
}
package cn.testSpringTransaction;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
//测试类
public class TransactionTest {
@Test
public void xmlTest(){
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContextTransaction.xml");
// 获取AccountDao实例
AccountDao accountDao =
(AccountDao)applicationContext.getBean("accountDao");
// 调用实例中的转账方法
accountDao.transfer("Jack", "Rose", 100.0);
// 输出提示信息
System.out.println("转账成功!");
}
@Test
public void annotationTest(){
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContextTransaction-annotation.xml");
// 获取AccountDao实例
AccountDao accountDao =
(AccountDao)applicationContext.getBean("accountDao");
// 调用实例中的转账方法
accountDao.transfer("Jack", "Rose", 100.0);
// 输出提示信息
System.out.println("转账成功!");
}
}