Hibernate学习5 事务管理简单例子购买股票

来源:互联网 发布:河北大学工商学院 知乎 编辑:程序博客网 时间:2024/05/16 11:36

Spring与JDBC模板 需要注意的是:
//getJdbcTemplate模板对象是多例的,只在一个方法内有效,当前线程有效,系统会为每一个使用模板对象的方法创建爱一个getJdbcTemplate模板,当
//该方法结束之后便自动销毁,只局限于当前方法 这个类的使用方法是错误的,会报空指针异常
private JdbcTemplate jt;
public StudentDaoImpl() {
jt = this.getJdbcTemplate();
}
@Override
public void insertStudent(Student student) {
String sql = “insert into student(name,age) value(?,?)”;
this.jt.update(sql,student.getName(),student.getAge()) ;
}
Spring的事务管理:
原子性: server层调用DAO层 要成功都成功,不成功都不成功
主要是把DAO层提升到server层
Spring中通常可以通过三种方式通过以下三种方法实现对事务的管理:
事务属于系统级服务,将来作为切面出现,把需要做的操作织入到主业务中,切入点实际上就是server层的方法,只要指定了切入点,又指定了切面(事务),就可以把事务织入到方法层的server上(系统级方法调用AOP(切面),我们需要给织入主业务,织入点就是主业务的server层)把事务织入到server层的方法上 这就是我们实现的思路
Spring事务管理API:接口
必须保证记住,理解记忆
Spring的回滚方式:默认方式:发生运行时异常时发生回滚(严重),发生受查时异常时提交(编译时异常)
运行时异常虚拟机直接挂掉,受查时异常可以挽救通过捕捉异常 受查异常可以由程序员可以设置其回滚方式
Spring事务定义接口:
oracal的隔离级别 isolation 默认为2 级
MySQL默认的隔离级别是 4级
事务定义了七个事务传播行为常量

  此配置文件没有采用事务管理,所以购买股票的时候,出现了数据库中账户金额减少了,但是股票数目没有增加的不一致情况。
  下面说一下其中一个demo
  首先是整个框架结构
  用到的jar包和框架结构
实体类:银行账户 Accoount.java

package com.vrv.yinkailong.bean;//银行账户public class Accoount {    private Integer aid;    private String aname;     //账户名称    private double balance;   // 账户余额    public Accoount() {        super();    }    public Accoount(String aname, double balance) {        super();        this.aname = aname;        this.balance = balance;    }    public Integer getAid() {        return aid;    }    public void setAid(Integer aid) {        this.aid = aid;    }    public String getAname() {        return aname;    }    public void setAname(String aname) {        this.aname = aname;    }    public double getBalance() {        return balance;    }    public void setBalance(double balance) {        this.balance = balance;    }    @Override    public String toString() {        return "Accoount [aid=" + aid + ", aname=" + aname + ", balance=" + balance + "]";    }}

实体类: 股票账户 Stock.java

package com.vrv.yinkailong.bean;//股票账户public class Stock {    private Integer sid;    private String sname;   //股票名称    private int amount;     //股票数量    public Stock() {        super();    }    public Stock(String sname, int amount) {        super();        this.sname = sname;        this.amount = amount;    }    public Integer getSid() {        return sid;    }    public void setSid(Integer sid) {        this.sid = sid;    }    public String getSname() {        return sname;    }    public void setSname(String sname) {        this.sname = sname;    }    public int getAmount() {        return amount;    }    public void setAmount(int amount) {        this.amount = amount;    }    @Override    public String toString() {        return "Stock [sid=" + sid + ", sname=" + sname + ", amount=" + amount + "]";    }}

接着是service层: 定义接口 IBuyStockService.java

package com.vrv.yinkailong.service;import com.vrv.yinkailong.exception.BuyStockException;public interface IBuyStockService {    //开账户的方法    void openAccouont(String aname,double money);    void openStock(String sname,int count);    //买股票    void buyStock(String aname,double money,String sname,int count) throws BuyStockException;}

接口的实现

package com.vrv.yinkailong.service;import com.vrv.yinkailong.dao.IAccountDao;import com.vrv.yinkailong.dao.IStockDao;import com.vrv.yinkailong.exception.BuyStockException;public class BuyStockServiceImpl implements IBuyStockService {        private IAccountDao ado;        private IStockDao idao;   //必須要實現set方法    public void setAdo(IAccountDao ado) {            this.ado = ado;        }        public void setIdao(IStockDao idao) {            this.idao = idao;        }    @Override    public void openAccouont(String aname, double money) {        ado.insertAccount(aname,money);    }    @Override    public void openStock(String sname, int count) {         idao.insertStock(sname,count);    }    @Override    public void buyStock(String aname, double money, String sname, int count) throws BuyStockException {          Boolean isBuy = true;         ado.updateAccount(aname,money,isBuy);         //人为的制造异常,然后引出事务    /*   if (true)          {              throw new BuyStockException("购买股票不成功!!!但是钱被扣了");        }*/          idao.updateStock(sname,count,isBuy);    }}

增加相应的dao层,因为实现中用到了相应的dao 接口 IAccountDao.java

package com.vrv.yinkailong.dao;public interface IAccountDao {    void insertAccount(String aname, double money);    void updateAccount(String aname, double money, Boolean isBuy);}

接口 : IStockDao.java

package com.vrv.yinkailong.dao;public interface IStockDao {    void insertStock(String sname, int count);    void updateStock(String sname, int count, Boolean isBuy);}

DAO接口的实现 AccountDaoImpl.java 需要继承 JdbcDaoSupport

package com.vrv.yinkailong.daoImpl;import org.springframework.jdbc.core.support.JdbcDaoSupport;import com.vrv.yinkailong.dao.IAccountDao;public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao{    @Override    public void insertAccount(String aname, double money) {    String sql = "insert into account(aname,balance) value(?,?)";    this.getJdbcTemplate().update(sql,aname,money);    }    @Override    public void updateAccount(String aname, double money, Boolean isBuy) {        //默认卖股票                //尤其需要主要sql里面语句增加和修改是在原字段基础上进行的修改,切勿写错了 balance        String sql = "update account set balance=balance+? where aname=?";        if (isBuy) {            //此处为买入股票增加股票数量             sql = "update account set balance=balance-? where aname=?";        }       this.getJdbcTemplate().update(sql,money,aname);    }}

DAO层的实现 StockDaoImpl.java 同理需要继承JdbcDaoSupport

package com.vrv.yinkailong.daoImpl;import org.springframework.jdbc.core.support.JdbcDaoSupport;import com.vrv.yinkailong.dao.IStockDao;public class StockDaoImpl extends JdbcDaoSupport implements IStockDao {    @Override    public void insertStock(String sname, int count) {        String sql = "insert into stock(sname,amount) value(?,?)";        this.getJdbcTemplate().update(sql,sname,count);    }    @Override    public void updateStock(String sname, int count, Boolean isBuy) {        //默认卖股票        String sql = "update stock set amount=amount-? where sname=?";        if (isBuy) {            //此处为买入股票增加股票数量             sql = "update stock set amount=amount+?  where sname=?";        }    this.getJdbcTemplate().update(sql,count,sname);    }}

下面是主配置文件 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">   <!-- -指定读取配置文件路径   加上context约束必须引入相应的头文件  常用方式context约束-->          <context:property-placeholder location="classpath:jdbc.properties"/>   <!-- -注册数据源-->         <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">         <property name="driverClass" value="com.mysql.jdbc.Driver"/>         <property name="jdbcUrl"  value="jdbc:mysql://127.0.0.1:3306/curd"/>         <property name="user" value="root"/>         <property name="password" value="123456"/>         </bean>      <!-- 指定读取配置文件路径   加上context约束必须引入相应的头文件  常用方式context约束    任意选其中一种方法即可-->        <!--   <context:property-placeholder location="classpath:jdbc.properties"/>          <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">         <property name="driverClass" value="${jdbc.driver}"/>         <property name="jdbcUrl"  value="${jdbc.url}"/>         <property name="user" value="${jdbc.user}"/>         <property name="password" value="${jdbc.password}"/>         </bean> -->        <bean id="IAccountdao" class="com.vrv.yinkailong.daoImpl.AccountDaoImpl">        <property name="dataSource" ref="dataSource"/>        </bean>        <bean id="IStockdao" class="com.vrv.yinkailong.daoImpl.StockDaoImpl">        <property name="dataSource" ref="dataSource"/>        </bean>       <!-- 注册Service -->       <bean id="BuyStockService" class="com.vrv.yinkailong.service.BuyStockServiceImpl">       <property name="ado" ref="IAccountdao"/>       <property name="idao" ref="IStockdao"/>       </bean></beans>

使用的jdbc.properties 配置文件

jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://127.0.0.1:3306/curdjdbc.user=rootjdbc.password=123456 

然后是测试类 MyTest.java

package com.vrv.yinkailong.test;import org.junit.Before;import org.junit.Test;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.vrv.yinkailong.exception.BuyStockException;import com.vrv.yinkailong.service.IBuyStockService;public class MyTest {    private IBuyStockService service;    @Before    public void testBefore()    {        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");         service = (IBuyStockService) ac.getBean("BuyStockService");         System.out.println("我执行了before()方法");    }    @Test    public void testOpen()    {        service.openAccouont("张三", 10000);        service.openStock("动力节点", 1);    }    //需要处理受查   异常   该方法是虚拟机调用    @Test    public void testBuyAccount() throws BuyStockException    {        service.buyStock("张三", 500, "动力节点", 5);    }}

此时的执行结果是没问题的
运行第一个测试方法,数据成功插入数据库
但是我们这里主要学习得是事务处理,很明显在购买股票过程很可能发生异常,需要我们进行处理,这里我们自定义一个异常类 BuyStockException.java

package com.vrv.yinkailong.exception;//买股票过程可能会发生异常    只要继承exception就会发生授权异常,必须进行处理public class BuyStockException extends Exception {    public BuyStockException() {        super();    }    public BuyStockException(String message) {        super(message);    }}

暂时代码只写到这里,如果还需要继续使用事务来处理异常,需要重新定义主配置文件
 此配置文件没有采用事务管理,所以购买股票的时候,出现了数据库中账户金额减少了,但是股票数目没有增加的不一致情况。

  使用 Spring 的事务代理工厂管理事务:

    该方式是,需要为目标类,即 Service 的实现类创建事务代理。事务代理使用的类是TransactionProxyFactoryBean,该类需要初始化如下一些属性:
      (1)transactionManager:事务管理器
      (2)target:目标对象,即 Service 实现类对象
      (3)transactionAttributes:事务属性设置
    对于 XML 配置代理方式实现事务管理时,受查异常的回滚方式,程序员可以通过以下方式进行设置:通过“-异常”方式,可使发生指定的异常时事务回滚;通过“+异常”方式,可使发生指定的异常时事务提交。
    明天继续补上!与君共勉,今天由于粗心大意,在数据库方面遇到一些问题,所以进度有点慢,明天继续补上!谢谢观看

原创粉丝点击