建立数据库
CREATE TABLE springaccount (
id INT ( 11 ) NOT NULL AUTO_INCREMENT,
NAME VARCHAR ( 32 ) NOT NULL,
ACCOUNT DOUBLE NOT NULL,
PRIMARY KEY ( id)
) ENGINE= INNODB DEFAULT CHARSET= utf8;
导入依赖jar包
< packaging> jar< / packaging>
< dependencies>
< dependency>
< groupId> org. springframework< / groupId>
< artifactId> spring- context< / artifactId>
< version> 5.2 .9 . RELEASE< / version>
< / dependency>
< dependency>
< groupId> org. springframework< / groupId>
< artifactId> spring- test< / artifactId>
< version> 5.2 .9 . RELEASE< / version>
< / dependency>
< dependency>
< groupId> commons- dbutils< / groupId>
< artifactId> commons- dbutils< / artifactId>
< version> 1.7 < / version>
< / dependency>
< dependency>
< groupId> mysql< / groupId>
< artifactId> mysql- connector- java< / artifactId>
< version> 8.0 .21 < / version>
< / dependency>
< dependency>
< groupId> c3p0< / groupId>
< artifactId> c3p0< / artifactId>
< version> 0.9 .1 .2 < / version>
< / dependency>
< dependency>
< groupId> junit< / groupId>
< artifactId> junit< / artifactId>
< version> 4.13 < / version>
< scope> test< / scope>
< / dependency>
< / dependencies>
建立实体类
public class Account implements Serializable {
private Integer id;
private String name;
private double account;
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 getAccount ( ) {
return account;
}
public void setAccount ( double account) {
this . account = account;
}
@Override
public String toString ( ) {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", account=" + account +
'}' ;
}
}
编写工具类
编写连接的工具类 它用于从数据源中获取一个连接,并且实现和线程的绑定
public class ConnectionUtils {
private ThreadLocal< Connection> tl = new ThreadLocal < > ( ) ;
private DataSource dataSource;
public void setDataSource ( DataSource dataSource) {
this . dataSource = dataSource;
}
public Connection getThreadConnection ( ) {
try {
Connection conn = tl. get ( ) ;
if ( conn == null) {
conn = dataSource. getConnection ( ) ;
tl. set ( conn) ;
}
return conn;
} catch ( Exception e) {
throw new RuntimeException ( e) ;
}
}
public void removeConnection ( ) {
tl. remove ( ) ;
}
}
编写和事务管理相关工具类 开启事务,提交事务,回滚事务,释放连接
public class TransactionManager {
private ConnectionUtils connectionUtils;
public void setConnectionUtils ( ConnectionUtils connectionUtils) {
this . connectionUtils = connectionUtils;
}
public void beginTransaction ( ) {
try {
connectionUtils. getThreadConnection ( ) . setAutoCommit ( false ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
}
public void commit ( ) {
try {
connectionUtils. getThreadConnection ( ) . commit ( ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
}
public void rollback ( ) {
try {
connectionUtils. getThreadConnection ( ) . rollback ( ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
}
public void release ( ) {
try {
connectionUtils. getThreadConnection ( ) . close ( ) ;
connectionUtils. removeConnection ( ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
}
}
创建Service代理工厂
public class BeanFactory {
private AccountService accountService;
private TransactionManager txManager;
public void setAccountService ( AccountService accountService) {
this . accountService = accountService;
}
public final void setTxManager ( TransactionManager txManager) {
this . txManager = txManager;
}
public AccountService getAccountService ( ) {
return ( AccountService) Proxy. newProxyInstance ( accountService. getClass ( ) . getClassLoader ( ) ,
accountService. getClass ( ) . getInterfaces ( ) ,
new InvocationHandler ( ) {
@Override
public Object invoke ( Object proxy, Method method, Object[ ] args) throws Throwable {
Object rtValue = null;
try {
txManager. beginTransaction ( ) ;
rtValue = method. invoke ( accountService, args) ;
txManager. commit ( ) ;
return rtValue;
} catch ( Exception e) {
txManager. rollback ( ) ;
throw new RuntimeException ( e) ;
} finally {
txManager. release ( ) ;
}
}
} ) ;
}
}
业务层
public class AccountServiceImp implements AccountService {
private AccountDao accountDao;
public void setAccountDao ( AccountDao accountDao) {
this . accountDao = accountDao;
}
public void transfer ( String sourceName, String targetName, float money) {
Account sourceAccount = accountDao. findAccountByName ( sourceName) ;
Account targetAccount = accountDao. findAccountByName ( targetName) ;
sourceAccount. setAccount ( sourceAccount. getAccount ( ) - money) ;
targetAccount. setAccount ( targetAccount. getAccount ( ) + money) ;
accountDao. updateAccount ( sourceAccount) ;
accountDao. updateAccount ( targetAccount) ;
}
}
持久层
public class AccountDaoImp implements AccountDao {
private QueryRunner queryRunner;
private ConnectionUtils connectionUtils;
public void setQueryRunner ( QueryRunner queryRunner) {
this . queryRunner = queryRunner;
}
public void setConnectionUtils ( ConnectionUtils connectionUtils) {
this . connectionUtils = connectionUtils;
}
public Account findAccountByName ( String name) {
try {
List< Account> accounts = queryRunner. query ( connectionUtils. getThreadConnection ( ) , "select * from springaccount where name=?" , new BeanListHandler < > ( Account. class ) , name) ;
if ( accounts == null || accounts. size ( ) == 0 ) {
return null;
}
if ( accounts. size ( ) > 1 ) {
throw new RuntimeException ( "结果不唯一,数据有问题" ) ;
}
return accounts. get ( 0 ) ;
} catch ( Exception e) {
throw new RuntimeException ( e) ;
}
}
@Override
public void updateAccount ( Account account) {
try {
queryRunner. update ( connectionUtils. getThreadConnection ( ) , "update springaccount set name=? ,account=? where id=?" , account. getName ( ) , account. getAccount ( ) , account. getId ( ) ) ;
} catch ( Exception e) {
throw new RuntimeException ( e) ;
}
}
}
测试方法
@RunWith ( SpringJUnit4ClassRunner. class )
@ContextConfiguration ( locations = "classpath:bean.xml" )
public class AccountServiceTset {
@Autowired
@Qualifier ( ( "proxyAccountService" ) )
private AccountService accountService;
@Test
public void testFindAllUsers ( ) {
accountService. transfer ( "张三" , "李四" , 100 ) ;
}
}
配置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">
< ! -- 配置代理的Service -- >
< bean id= "proxyAccountService" factory- bean= "beanFactory" factory- method= "getAccountService" > < / bean>
< ! -- 配置beanFactory -- >
< bean id= "beanFactory" class = "com.whut.factory.BeanFactory" >
< ! -- 注入Service-- >
< property name= "accountService" ref= "accountService" > < / property>
< ! -- 注入事务管理器-- >
< property name= "txManager" ref= "txManager" > < / property>
< / bean>
< ! -- 配置service-- >
< bean id= "accountService" class = "com.whut.service.imp.AccountServiceImp" >
< ! -- 注入Dao-- >
< property name= "accountDao" ref= "accountDao" > < / property>
< / bean>
< ! -- 配置Dao对象-- >
< bean id= "accountDao" class = "com.whut.dao.imp.AccountDaoImp" >
< ! -- 注入QueryRunner-- >
< property name= "queryRunner" ref= "queryRunner" > < / property>
< ! -- 注入ConnectionUtils -- >
< property name= "connectionUtils" ref= "connectionUtils" > < / property>
< / bean>
< ! -- 配置QueryRunner-- >
< bean id= "queryRunner" class = "org.apache.commons.dbutils.QueryRunner" scope= "prototype" > < / bean>
< bean id= "txManager" class = "com.whut.utils.TransactionManager" >
< ! -- 注入ConnectionUtils -- >
< property name= "connectionUtils" ref= "connectionUtils" > < / property>
< / bean>
< bean id= "connectionUtils" class = "com.whut.utils.ConnectionUtils" >
< ! -- 注入数据源-- >
< property name= "dataSource" ref= "dataSource" > < / property>
< / bean>
< ! -- 配置数据源-- >
< bean id= "dataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource" >
< ! -- 连接数据库必备信息-- >
< property name= "driverClass" value= "com.mysql.cj.jdbc.Driver" / >
< property name= "jdbcUrl" value= "jdbc:mysql://localhost:3306/my_db?serverTimezone=UTC" / >
< property name= "user" value= "root" / >
< property name= "password" value= "fy123" / >
< / bean>
< / beans>