Spring练习:JDBC模板和事务回滚
来源:互联网 发布:诺基亚6730c软件 编辑:程序博客网 时间:2024/06/03 07:13
SSH框架是每个学生毕业前都必须掌握的一门技术,所以这里就用Spring的JDBC模板和自定义异常让事务回滚来做一个练习。主要用到的是spring和struts2框架来操作,这里暂时没用Hibernate来对数据进行操作。
一、练习要求。
要求写一个用户购买股票的项目,用户先开户后登陆,可以在里面买股票和卖股票,当买股票金额超过用户金额时就报异常让事务回滚,用户卖出股票时超过持有数量报异常让事务回滚。
二、数据库表
这里因为没有用到Hibernate所以不能通过配置实体类创建表,所以只能手动创建,表结构如下:
person表;
stock表
三、创建包和配置好所需的配置文件
先导入spring和struts2所需要用到的包,再创建配置文件,然后我们再新建对应的Package。
四、开户和登录
买或卖股票之前每个人都有自己的账户来存自己的金额和信息,这里先设计好jsp页面让用户进行选择是开户还是登录。(这里只是简单的弄了下jsp页面)
点击开户就进到另一个jsp页面来进行操作
到写数据操作语句,这里要先对用户名进行排重下,以免重复账户。先到Dao层写好接口,让DaoImp层实现接口。
DaoImp实现接口时也要继承下JdbcDaoSupport这样才能对数据进行处理。
public class ZhuCeDaoImp extends JdbcDaoSupport implements ZhuCeDao{@Overridepublic boolean addUser(Person p) {System.out.println("进入开户~~~");//排重,如果为true就直接返回false;if(this.touser(p.getUserName())){return false;}//如果排除为false,就好进行添加用户,这里我们传实体类就可以获取到对应的参数。String sql = "insert into person(username,password,money) value (?,?,?)";//直接this关键字调用继承父类的方法来操作sql语句int i = this.getJdbcTemplate().update(sql,p.getUserName(),p.getPassWord(),p.getMoney());if(i!=0){//判断下,在后台输出看是否成功System.out.println("开户成功");return true;}else{System.out.println("开户失败");return false;}}//用户名排重public boolean touser(String name){System.out.println("进入排重~~~");//查找对应的用户名String sql = "select username from person where username=?";List s = this.getJdbcTemplate().queryForList(sql, String.class,name);//存的是List类型,所以list不为空就是该用户名已存在,反之则没有if(s.size()!=0){return true;}return false;}}再写Service层接口,让ServiceImp层实现,Service层接口的方法就是Dao层接口的方法,所以为了方便集中把所以的Dao层接口方法都写在了一个Service层接口里面,ServiceImp层也是直接调用Dao层对象来实现全部方法。
Service层
public interface TestService {//用户开户public boolean addUser(Person p);//用户登录public boolean toLogin(Person p);//买股票public boolean tobuy(String stockName,String username,int count) throws MyException;//卖股票public boolean tosell(String stockName,String username,int count) throws MyException;//获取登录用户的所以股票信息public List<Stock> getUser(String userName);//获取登录用户的总价public double getMoney(String userName);}当用户填写完form表单后点击开户提交就会通过struts2调用对应的action层,action层再调用Service层来对数据进行操作,要配置好spring配置文件。
public class ZhuCeKZ extends ActionSupport{//创建实体类,通过反射可以获取到form表单的提交数据,//但form表单的名字必须和实体类属性名相同,提供set,get方法,private Person p;public String toZhuCe(){//spring自动创建Service对象ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");TestService ts = (TestService) ac.getBean("textS");//调用开户处理,true就跳到登录视图,false就跳回注册视图重新注册if(ts.addUser(p)){return "success";}else{return "shibai";}}public Person getP() {return p;}public void setP(Person p) {this.p = p;}}成功注册后,就进入登录的jsp页面。
也是先写好Dao层接口和让DaoImp实现,再Service层接口让ServiceImp实现
Dao层
public interface LoginDao {public boolean toLogin(Person p);}DaoImp层
public class LoginDaoImp extends JdbcDaoSupport implements LoginDao{@Overridepublic boolean toLogin(Person p) {System.out.println("进入登录~~~");//先根据用户名查下是否存在String sql = "select * from person where username=?";//因为Person不是基本数据类型,所以要先自定义类型下RowMapper<Person> rowMapper = new BeanPropertyRowMapper<Person>(Person.class); List<Person> list = this.getJdbcTemplate().query(sql, rowMapper,p.getUserName());//存在List里面,判断下为空表示没有改数据if(list.size()!=0){//不为空的话就让查询到的实体和登录的实体密码就行判断if(list.get(0).getPassWord().equals(p.getPassWord())){return true;}}return false;}}
form表单提交跳到对应Action层,调用Service对象操作。
public class LoginKZ extends ActionSupport{private Person p;public String toLogin(){ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");TestService ts = (TestService) ac.getBean("textS");if(ts.toLogin(p)){//把用户名存进session里面在页面显示下,和后面方便数据存取ActionContext.getContext().getSession().put("username", p.getUserName());return "success";}return "shibai";}public Person getP() {return p;}public void setP(Person p) {this.p = p;}}
五、股票的买和卖
成功登录后就会跳到一个功能界面,用来购买股票和查看用户持有股。
当点击股票市场时就会进入查看股票价格,买卖股票可以输入对应的数量,所以用了些js来操作。
先写好Dao层的数据操作。
Dao层接口
public interface TradeDao {//买股票public boolean tobuy(String stockName,String username,int count);//卖股票public boolean tosell(String stockName,String username,int count);//获取登录用户的所以股票信息public List<Stock> getUser(String userName);//获取登录用户的总价public double getMoney(String userName);}DaoImp层
public class TradeDaoImp extends JdbcDaoSupport implements TradeDao{//买股票处理@Overridepublic boolean tobuy(String stockName, String username, int count) {System.out.println(username+"买"+stockName+"股票数量:"+count);//调用写好的排除股票重复方法if(this.getBuy(stockName, username)){//重复就直接更新股票数量String sql = "update stock set number=number+? where stockName=? and userName=?";this.getJdbcTemplate().update(sql,count,stockName,username);//调用写好的(购买股票数量*股票价格)方法,来进行对用户金额的加减double money = this.zeng(count, stockName);String sql2 = "update person set money=money-? where userName=?";this.getJdbcTemplate().update(sql2,money,username);System.out.println("购买股票成功");return true;}//如果排重为false就是新购买,所以要新添加股票信息进数据库String sql = "insert into stock(stockName,userName,number) value(?,?,?)";int i = this.getJdbcTemplate().update(sql,stockName,username,count);//如果成功就调用写好的(购买股票数量*股票价格)方法,来进行对用户金额的加减if(i!=0){double money = this.zeng(count, stockName);String sql2 = "update person set money=money-? where userName=?";this.getJdbcTemplate().update(sql2,money,username);System.out.println("购买股票成功");return true;}System.out.println("购买股票失败");return false;}//卖股票处理@Overridepublic boolean tosell(String stockName, String username, int count) {System.out.println(username+"卖"+stockName+"股票数量:"+count);//调用写好的方法,判断卖出数量是否超过持有数,超过就直接返回falseint cou = this.getStock(stockName, username);if(cou<count){return false;}//调用排重方法,false就是没持有改股票,true就是持有该股票if(this.getBuy(stockName, username)){//持有股票数量减去卖出数量String sql = "update stock set number=number-? where stockName=? and userName=?";this.getJdbcTemplate().update(sql,count,stockName,username);//调用写好的(购买股票数量*股票价格)方法,来进行对用户金额的加减double money = this.zeng(count, stockName);String sql2 = "update person set money=money+? where userName=?";this.getJdbcTemplate().update(sql2,money,username);return true;}return false;}//遍历出用户股票数量@Overridepublic List<Stock> getUser(String userName) {System.out.println("遍历用户股票");String sql = "select * from stock where userName=?";//因为Stock不是基本数据类型,所以要先自定义类型下RowMapper<Stock> rowMapper = new BeanPropertyRowMapper<Stock>(Stock.class); List<Stock> list =this.getJdbcTemplate().query(sql,rowMapper,userName);return list;}//获取剩余资产@Overridepublic double getMoney(String userName) {String sql = "select money from person where userName=?";double money = this.getJdbcTemplate().queryForObject(sql, Double.class,userName);return money;}//自定义方法//股票排重public boolean getBuy(String stockName, String username){String sql = "select * from stock where stockName=?";RowMapper<Stock> rowMapper = new BeanPropertyRowMapper<Stock>(Stock.class); List<Stock> list = this.getJdbcTemplate().query(sql,rowMapper,stockName);if(list.size()!=0){for(int i=0;i<list.size();i++){if(list.get(i).getUserName().equals(username)){return true;}}}return false;}//判断类型对money进行加减public double zeng(int count,String type){double i = 0;//因为这里没存进数据库,所以直接写死if(type.equals("华为")){i = count*200;}if(type.equals("网易")){i = count*300;}if(type.equals("三星")){i = count*20;}return i;}//获取已有的股票数,来判断是否超过卖出的数量public int getStock(String stockName,String userName){String sql = "select number from stock where stockName=? and userName=?";int i = this.getJdbcTemplate().queryForInt(sql, stockName,userName);return i;}}
当用户输入数量点击买卖股票时,就会跳到对应的Action层来调用Service对象,ServiceImp层直接调用Dao层对象来操作。
public class StockKZ {//股票名,jsp页面传过来private String stockName;//股票数量,jsp页面传过来private int count;//登录用户持有股票private ArrayList list;//总价private double money;//定义成成员变量方便调用ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");//这里调用的是代理对象TestService ts = (TestService) ac.getBean("serviceProxy");//买股票控制public String toBuy(){//用户名在登录时已经存进session里面,所以可以获取到String username = ActionContext.getContext().getSession().get("username").toString();try {if(ts.tobuy(stockName, username, count)){return "success";}} catch (MyException e) {e.printStackTrace();}return "shibai";}//卖股票控制public String toSell(){String username = ActionContext.getContext().getSession().get("username").toString();try {if(ts.tosell(stockName, username, count)){return "success";}} catch (MyException e) {e.printStackTrace();}return "shibai";}//查看资产和持股票数量public String getZiCang() {String userName = ActionContext.getContext().getSession().get("username").toString();list = (ArrayList) ts.getUser(userName);money = ts.getMoney(userName);return "success2";}//set,getpublic void setStockName(String stockName) {this.stockName = stockName;}public int getCount() {return count;}public void setCount(int count) {this.count = count;}public void setList(ArrayList list) {this.list = list;}public ArrayList getList() {return list;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}}
这样就可以买卖股票,在页面上显示登录用户持有股票和剩余金额
六、事务的回滚
如何让事务回滚,这里就要自定义异常,当有异常时就会让事务回滚,从而让数据没有改变。所以我们在买卖股票时加下判断,这里就要到ServiceImp层操作
public class TestServiceImp implements TestService{//开户Daoprivate ZhuCeDao zd;//登录Daoprivate LoginDao ld;//股票操作Daoprivate TradeDao td;//用户开户@Overridepublic boolean addUser(Person p) {return zd.addUser(p);}//用户登录@Overridepublic boolean toLogin(Person p) {return ld.toLogin(p);}//买股票@Overridepublic boolean tobuy(String stockName, String username, int count) throws MyException {td.tobuy(stockName, username, count);//获取下剩余的资产double money = this.getMoney(username);//如果小于0就抛异常,让事务回滚if(money<0){throw new MyException("你已经没有钱了~~~");}return true;}//卖股票@Overridepublic boolean tosell(String stockName, String username, int count) throws MyException {//获取下用户的全部持有股票信息List list = this.getUser(username);if(list.size()!=0){//不为空就遍历for(int i=0;i<list.size();i++){Stock stock = (Stock) list.get(i);//匹配股票名字是否相同,相同就判断用户持有该股票数量//如果小于等于0就抛异常,让事务回滚if(stockName.equals(stock.getStockName())&&stock.getNumber()<=0){throw new MyException("你已经没有该公司的股票~~~"); }}}return td.tosell(stockName, username, count);}//登录用户持有股票@Overridepublic List<Stock> getUser(String userName){List list = td.getUser(userName);return list;}//获取总价@Overridepublic double getMoney(String userName) {return td.getMoney(userName);}//setpublic void setZd(ZhuCeDao zd) {this.zd = zd;}public void setLd(LoginDao ld) {this.ld = ld;}public void setTd(TradeDao td) {this.td = td;}}如果抛出异常后台就会输出异常信息。
最后
spring的配置文件才是最重要的,所以来看下applicationContext.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" 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"> <!-- 注册数据源 (spring内置数据库源)--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <!-- 注册数据库属性文件 方式一 --> <beanclass="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:jdbc.properties" /> </bean> <!-- 注册事务管理器 --> <beanid="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 生成service的事务代理对象 --> <bean id="serviceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <!-- 目标对象 --> <property name="target" ref="textS" /> <!-- 跟事务管理器关联 --> <property name="transactionManager" ref="transactionManager" /> <property name="transactionAttributes"> <props> <prop key="to*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-MyException</prop> </props> </property> </bean> <!-- 注册Dao对象 --> <!-- 开户Dao --> <bean id="zhuceD" class="com.it.DaoImp.ZhuCeDaoImp"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 登录Dao --> <bean id="loginD" class="com.it.DaoImp.LoginDaoImp"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 股票操作Dao --> <bean id="tradeD" class="com.it.DaoImp.TradeDaoImp"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 注册Service对象 --> <bean id="textS" class="com.it.ServiceImp.TestServiceImp"> <property name="zd" ref="zhuceD"></property> <property name="ld" ref="loginD"></property> <property name="td" ref="tradeD"></property> </bean></beans>
- Spring练习:JDBC模板和事务回滚
- jdbc事务-回滚
- Spring事务和异常回滚
- Spring事务回滚和异常类
- 配置Spring JDBC的事务回滚失效
- Spring事务回滚
- spring事务回滚
- spring事务回滚
- spring事务回滚
- spring回滚事务
- spring 事务回滚
- spring 事务回滚
- spring事务回滚
- Spring事务回滚
- [Spring]事务回滚
- Spring事务回滚
- spring事务回滚
- JDBC-数据库事务回滚
- 编写 Node.js Rest API 的 10 个最佳实践
- 简述交换机和路由器的区别
- Axure 8.0.0.3312可用注册码
- Struts2环境搭建、创建Action并测试启动、核心文件介绍、配置文件连接点详述
- MyEclipse Eclipse敲击@符号没有提示的解决方法
- Spring练习:JDBC模板和事务回滚
- 达内代码下载地址
- java三大框架之Spring
- 华行编译文件Makefile
- composer安装yii时遇到token问题
- 设备像素比(devicePixelRatio)
- 一周总结 app换肤和夜间模式问题
- spring事务详解
- Netty权威指南 第2版学习笔记9——Channel,Unsafe和 AttributeMap