流程图:
项目结构:
代码:
package com.csdn3.SpringJDBC;
public class Account {
private Integer 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;
}
@Override
public String toString() {
return "Account [id=" + id + ", username=" + username + ", balance=" + balance + "]";
}
}
package com.csdn3.SpringJDBC;
import java.util.List;
public interface AccountDao {
public int addAccount(Account account);
public int updateAccount(Account account);
public int deleteAccount(int id);
public Account findAccountById(int id);
public List<Account> findAllAccount();
}
package com.csdn3.SpringJDBC;
import java.util.List;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
public class AccountDaoImplement implements AccountDao{
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public int addAccount(Account account) {
// TODO Auto-generated method stub
String sql="insert into account(username,balance) value (?,?)";
Object[] objects=new Object[] {
account.getUsername(),
account.getBalance()
};
//执行添加操作,返回的是受影响的记录条数
int num=this.jdbcTemplate.update(sql,objects);
return num;
}
@Override
public int updateAccount(Account account) {
// TODO Auto-generated method stub
String sql="update account set username=?,balance=? where id=?";
Object[] objects=new Object[] {
account.getUsername(),
account.getBalance(),
account.getId()
};
int num=this.jdbcTemplate.update(sql,objects);
return num;
}
@Override
public int deleteAccount(int id) {
// TODO Auto-generated method stub
String sql="delete from account where id=?";
int num=this.jdbcTemplate.update(sql,id);
return num;
}
@Override
public Account findAccountById(int id) {
// TODO Auto-generated method stub
String sql="select * from account where id=?";
RowMapper<Account> rowMapper=new BeanPropertyRowMapper<Account>(Account.class);
return this.jdbcTemplate.queryForObject(sql,rowMapper,id);
}
@Override
public List<Account> findAllAccount() {
// TODO Auto-generated method stub
String sql="select * from account ";
RowMapper<Account> rowMapper=new BeanPropertyRowMapper<Account>(Account.class);
return this.jdbcTemplate.query(sql, rowMapper);
}
}
说明:BeanPropertyRowMapper是RowMapper接口的实现类,它可以自动地将数据表中的数据映射到用户自定义的类中(前提是用户自定义类中的字段要与数据表的字段对应),创建完BeanPropertyRowMapper对象之后,在findXXX()方法中通过queryForObject()方法返回一个Object类型的单行记录;通过query()方法返回一个结果集合。
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/javaee"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="accountDao" class="com.csdn3.SpringJDBC.AccountDaoImplement">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<!-- more bean definitions go here -->
</beans>
package com.csdn3.SpringJDBC;
import java.util.List;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test {
@Test
public void addAccountTest() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("com/csdn3/SpringJDBC/ac.xml");
AccountDao accountdao=(AccountDao)applicationContext.getBean("accountDao");
Account account=new Account();
account.setUsername("xumaoyan");
account.setBalance(10000.00);
int num=accountdao.addAccount(account);
if(num>0)System.out.println("成功插入了"+num+"条数据");
else System.out.println("插入操作有误!");
}
@Test
public void findAccountTest() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("com/csdn3/SpringJDBC/ac.xml");
AccountDao accountdao=(AccountDao)applicationContext.getBean("accountDao");
Account account=accountdao.findAccountById(15);
System.out.println(account);
}
@Test
public void findAllAccountTest() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("com/csdn3/SpringJDBC/ac.xml");
AccountDao accountdao=(AccountDao)applicationContext.getBean("accountDao");
List<Account> account=accountdao.findAllAccount();
for(Account act:account) {
System.out.println(act);
}
}
}
最后一个Test下的的运行效果图:
我的数据库:
Spring的事务管理:
本章将在上面代码的基础上进行讲解:
基于xml方式的声明式事务:
流程图:
在AcountDao接口中增加一个转账方法:
public void transfer(String outUser,String inUser,Double money);
在AccountDaoImplement实现类中编辑转账方法
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);
// TODO Auto-generated method stub
}
说明这里故意模拟系统执行转账过程中的突发情况,当这个方法执行的时候,事务管理将撤销上一步操作
将ac.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: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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/javaee"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="accountDao" class="com.csdn3.SpringJDBC.AccountDaoImplement">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<!-- more bean definitions go here -->
<!--注册事务管理器-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="txManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--事务的属性配置-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
</tx:attributes>
</tx:advice>
<!--切点的织入-->
<aop:config>
<aop:pointcut id="txPoint" expression="execution(* com.csdn3.SpringJDBC.*.*(..))"/>
<aop:advisor pointcut-ref="txPoint" advice-ref="txAdvice"/>
</aop:config>
</beans>
在test类中写单元测试类:
@Test
public void Transfer() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("com/csdn3/SpringJDBC/ac.xml");
AccountDao accountdao=(AccountDao)applicationContext.getBean("accountDao");
accountdao.transfer("xumaoyan", "hq", 2000.00);
System.out.println("转账成功");
}
运行测试:
单元测试确实报了:/by zero错误。检查数据库,数据没有改变。
撤销错误,转账操作执行,转账成功。
基于Annotation方式的声明式事务:
只需要将切点的织入部分更改为以下配置即可,然后在需要使用事务的方法上使用@Transaction注解
<tx:annotation-driven transaction-manager="txManager"/>
需要注意的是,当项目中需要实例化的bean过多的时候,要开启注解处理器。这里因为配置了实现类的bean,而事务的注解也正好配置在该bean中,所以直接生效了。