赞
踩
pom.xml
<?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>day02_eesy_02account_xmlioc</artifactId> <version>1.0-SNAPSHOT</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>6</source> <target>6</target> </configuration> </plugin> </plugins> </build> <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-test</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</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.12</version> </dependency> </dependencies> </project>
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 + '}'; } }
service serviceImpl
/** * 账户的业务层接口 */ public interface IAccountService { /** * 查询所有 * @return */ List<Account> findAllAccount(); /** * 查询一个 * @return */ Account findAccountById(Integer accountId); /** * 保存 * @param account */ void saveAccount(Account account); /** * 更新 * @param account */ void updateAccount(Account account); /** * 删除 * @param acccountId */ void deleteAccount(Integer acccountId); /** * 转账 * @param sourceName 转出账户名称 * @param targetName 转入账户名称 * @param money 转账金额 */ void transfer(String sourceName,String targetName,Float money); } /** * 账户的业务层实现类 * * 事务控制应该都是在业务层 */ public class AccountServiceImpl_old implements IAccountService { private IAccountDao accountDao; private TransactionManager txManager; public void setTxManager(TransactionManager txManager) { this.txManager = txManager; } public void setAccountDao(IAccountDao accountDao) { this.accountDao = accountDao; } @Override public List<Account> findAllAccount() { try { //1.开启事务 txManager.beginTransaction(); //2.执行操作 List<Account> accounts = accountDao.findAllAccount(); //3.提交事务 txManager.commit(); //4.返回结果 return accounts; } catch (Exception e) { //5.回滚操作 txManager.rollback(); throw new RuntimeException(e);//产生异常程序不再运行 }finally { //6.释放连接 txManager.release(); } } @Override public Account findAccountById(Integer accountId) { try { //1.开启事务 txManager.beginTransaction(); //2.执行操作 Account account = accountDao.findAccountById(accountId); //3.提交事务 txManager.commit(); //4.返回结果 return account; } catch (Exception e) { //5.回滚操作 txManager.rollback(); throw new RuntimeException(e); }finally { //6.释放连接 txManager.release(); } } @Override public void saveAccount(Account account) { try { //1.开启事务 txManager.beginTransaction(); //2.执行操作 accountDao.saveAccount(account); //3.提交事务 txManager.commit(); } catch (Exception e) { //5.回滚操作 txManager.rollback(); }finally { //6.释放连接 txManager.release(); } } @Override public void updateAccount(Account account) { try { //1.开启事务 txManager.beginTransaction(); //2.执行操作 accountDao.updateAccount(account); //3.提交事务 txManager.commit(); } catch (Exception e) { //5.回滚操作 txManager.rollback(); }finally { //6.释放连接 txManager.release(); } } @Override public void deleteAccount(Integer acccountId) { try { //1.开启事务 txManager.beginTransaction(); //2.执行操作 accountDao.deleteAccount(acccountId); //3.提交事务 txManager.commit(); } catch (Exception e) { //5.回滚操作 txManager.rollback(); }finally { //6.释放连接 txManager.release(); } } //转账 @Override public void transfer(String sourceName, String targetName, Float money) { try { //1.开启事务 txManager.beginTransaction(); //2.执行操作 //2.1根据名称查询转出账户 Account source = accountDao.findAccountByName(sourceName); //2.2根据名称查询转入账户 Account targe = accountDao.findAccountByName(targetName); //2.3转出账户减钱 source.setMoney(source.getMoney() - money); //2.4转入账户价钱 targe.setMoney(targe.getMoney() + money); //2.5更新转出账户 accountDao.updateAccount(source); //2.6更新转入账户 accountDao.updateAccount(targe); //3.提交事务 txManager.commit(); } catch (Exception e) { //5.回滚操作 txManager.rollback(); e.printStackTrace(); }finally { //6.释放连接 txManager.release(); } } }
dao daoImpl
/** * 账户的持久层接口 */ public interface IAccountDao { /** * 查询所有 * @return */ List<Account> findAllAccount(); /** * 查询一个 * @return */ Account findAccountById(Integer accountId); /** * 保存 * @param account */ void saveAccount(Account account); /** * 更新 * @param account */ void updateAccount(Account account); /** * 删除 * @param acccountId */ void deleteAccount(Integer acccountId); /** * 根据名称查询账户 * @param accountName * @return 如果有唯一的结果就返回,如果没有结果就返回null * 如果结果集超过一个就抛出异常 */ Account findAccountByName(String accountName); } /** * 账户的持久层实现类 */ public class AccountDaoImpl implements IAccountDao { private QueryRunner runner; private ConnectioUtils connectioUtils; public void setConnectioUtils(ConnectioUtils connectioUtils) { this.connectioUtils = connectioUtils; } public void setRunner(QueryRunner runner) { this.runner = runner; } @Override public List<Account> findAllAccount() { try{ return runner.query(connectioUtils.getThreadConnection(),"select * from account",new BeanListHandler<Account>(Account.class)); }catch (Exception e) { throw new RuntimeException(e); } } @Override public Account findAccountById(Integer accountId) { try{ return runner.query(connectioUtils.getThreadConnection(),"select * from account where id = ? ",new BeanHandler<Account>(Account.class),accountId); }catch (Exception e) { throw new RuntimeException(e); } } @Override public void saveAccount(Account account) { try{ runner.update(connectioUtils.getThreadConnection(),"insert into account(name,money)values(?,?)",account.getName(),account.getMoney()); }catch (Exception e) { throw new RuntimeException(e); } } @Override public void updateAccount(Account account) { try{ runner.update(connectioUtils.getThreadConnection(),"update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId()); }catch (Exception e) { throw new RuntimeException(e); } } @Override public void deleteAccount(Integer accountId) { try{ runner.update(connectioUtils.getThreadConnection(),"delete from account where id=?",accountId); }catch (Exception e) { throw new RuntimeException(e); } } @Override public Account findAccountByName(String accountName) { try{ List<Account> accounts = runner.query(connectioUtils.getThreadConnection(),"select * from account where name = ? ",new BeanListHandler<Account>(Account.class),accountName); 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); } } }
utils
/** * 需要使用Threadlocal对象把Connection和当前线程绑定,从而使一个线程中只有一个能控制事务的对象 * 连接的工具类,用于从数据源中获取一个连接,并且实现线程的绑定 */ public class ConnectioUtils { private ThreadLocal<Connection> tl = new ThreadLocal<Connection>(); //让spring注入 private DataSource dataSource; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } /** * 获取当前线程上的连接 * @return */ public Connection getThreadConnection() { try { //1.先从ThreadLocal上获取 Connection conn = tl.get(); //2.判断当前线程上上是否有连接 if (conn == null) { //3.从数据源中获取一个连接,并且存入线程ThreadLocal中 conn = dataSource.getConnection(); tl.set(conn); } //4返回当前线程上的连接 return conn; } catch (Exception e) { throw new RuntimeException(e); } } /** * 把连接和线程解绑 */ public void removeConnection(){ tl.remove(); } } /** * 事务管理相关的工具类,包含了开启事务,提交事务,回滚事务,释放连接 */ public class TransactionManager { //提供一个connectioUtils方法,并提供set,让spring注入 private ConnectioUtils connectioUtils; public void setConnectioUtils(ConnectioUtils connectioUtils) { this.connectioUtils = connectioUtils; } /** * 开启事务 */ public void beginTransaction(){ try { connectioUtils.getThreadConnection().setAutoCommit(false); } catch (Exception e) { e.printStackTrace(); } } /** * 提交事务 */ public void commit(){ try { connectioUtils.getThreadConnection().commit(); } catch (Exception e) { e.printStackTrace(); } } /** * 回滚事务 */ public void rollback(){ try { connectioUtils.getThreadConnection().rollback(); } catch (Exception e) { e.printStackTrace(); } } /** * 释放连接 */ public void release(){ try { connectioUtils.getThreadConnection().close();//还回了连接池中 connectioUtils.removeConnection(); } catch (Exception e) { e.printStackTrace(); } } }
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"> <!-- 配置Service --> <bean id="accountService" class="sise.cn.service.impl.AccountServiceImpl"> <!-- 注入dao --> <property name="accountDao" ref="accountDao"></property> <!--注入事务管理器--> <property name="txManager" ref="txManager"></property> </bean> <!--配置Dao对象--> <bean id="accountDao" class="sise.cn.dao.Impl.AccountDaoImpl"> <!-- 注入QueryRunner --> <property name="runner" ref="runner"></property> <!--注入connectionUtils--> <property name="connectioUtils" 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/eesyioc"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> </bean> <!--配置connection的工具类 connectionUtils--> <bean id="connectionUtils" class="sise.cn.utils.ConnectioUtils"> <!--注入数据源--> <property name="dataSource" ref="dataSource"></property> </bean> <!--配置事务管理器--> <bean id="txManager" class="sise.cn.utils.TransactionManager"> <property name="connectioUtils" ref="connectionUtils"></property> </bean> </beans>
创建factory beanfactory类
/** * 用于创建service的代理对象的工厂 */ public class BeanFactory { private IAccountService accountService; private TransactionManager txManager; public void setTxManager(TransactionManager txManager) { this.txManager = txManager; } public final void setAccountService(IAccountService accountService) { this.accountService = accountService; } /** * 获取service的代理对象 * @return */ public IAccountService getAccountService() { return (IAccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(), accountService.getClass().getInterfaces(), new InvocationHandler() { /** * 添加事务的支持 * * @param proxy * @param method * @param args * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object rtvAlue = null; try { //1.开启事务 txManager.beginTransaction(); //2.执行操作 rtvAlue = method.invoke(accountService, args); //3.提交事务 txManager.commit(); //4.返回结果 return rtvAlue; } catch (Exception e) { //5.回滚操作 txManager.rollback(); throw new RuntimeException(e); } finally { //6.释放连接 txManager.release(); } } }); } }
serviceImpl
/** * 账户的业务层实现类 * * 事务控制应该都是在业务层 */ public class AccountServiceImpl implements IAccountService { private IAccountDao accountDao; public void setAccountDao(IAccountDao accountDao) { this.accountDao = accountDao; } @Override public List<Account> findAllAccount() { return accountDao.findAllAccount(); } @Override public Account findAccountById(Integer accountId) { return accountDao.findAccountById(accountId); } @Override public void saveAccount(Account account) { accountDao.saveAccount(account); } @Override public void updateAccount(Account account) { accountDao.updateAccount(account); } @Override public void deleteAccount(Integer acccountId) { accountDao.deleteAccount(acccountId); } //转账 @Override public void transfer(String sourceName, String targetName, Float money) { //2.1根据名称查询转出账户 Account source = accountDao.findAccountByName(sourceName); //2.2根据名称查询转入账户 Account targe = accountDao.findAccountByName(targetName); //2.3转出账户减钱 source.setMoney(source.getMoney() - money); //2.4转入账户价钱 targe.setMoney(targe.getMoney() + money); //2.5更新转出账户 accountDao.updateAccount(source); //2.6更新转入账户 accountDao.updateAccount(targe); } }
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"> <!--配置代理的service--> <bean id="proxyAccountService" factory-bean="beanfactory" factory-method="getAccountService"></bean> <!--配置beanfactory--> <bean id="beanfactory" class="sise.cn.factory.BeanFactory"> <!--注入service--> <property name="accountService" ref="accountService"></property> <!--注入事务管理器--> <property name="txManager" ref="txManager"></property> </bean> <!-- 配置Service --> <bean id="accountService" class="sise.cn.service.impl.AccountServiceImpl"> <!-- 注入dao --> <property name="accountDao" ref="accountDao"></property> </bean> <!--配置Dao对象--> <bean id="accountDao" class="sise.cn.dao.Impl.AccountDaoImpl"> <!-- 注入QueryRunner --> <property name="runner" ref="runner"></property> <!--注入connectionUtils--> <property name="connectioUtils" 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/eesyioc"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> </bean> <!--配置connection的工具类 connectionUtils--> <bean id="connectionUtils" class="sise.cn.utils.ConnectioUtils"> <!--注入数据源--> <property name="dataSource" ref="dataSource"></property> </bean> <!--配置事务管理器--> <bean id="txManager" class="sise.cn.utils.TransactionManager"> <property name="connectioUtils" ref="connectionUtils"></property> </bean> </beans>
test:
/** * 使用Junit单元测试:测试我们的配置 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:bean.xml") public class AccountServiceTest { @Autowired @Qualifier("proxyAccountService") private IAccountService as; @Test public void testTransfer(){ as.transfer("aaa", "bbb", 100f); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。