您现在的位置是:首页 >

spring事务实现方式 spring是如何对Service进行事务管理的

火烧 2022-05-07 02:29:38 1092
ri g是如何对Service进行事务管理的   本人也很想弄清楚 ri g是如何对Service进行事务管理的 并且还去看了一下 ri g框架关于事务管理几个相关类的源码 可惜由于本人功力有限 只

spring是如何对Service进行事务管理的  

  本人也很想弄清楚spring是如何对Service进行事务管理的 并且还去看了一下spring框架关于事务管理几个相关类的源码 可惜由于本人功力有限 只看懂了皮毛.

  既然源代码看不懂 那么只有运用例子进行测试 虽然笨了点 不过管是白猫还是黑猫 能捉老鼠就是好猫. )

  为引起不必要的争论 本帖子只针对本案例的测试结果进行小结 并保证此测试代码在本人的运行环境绝对正确.

  开发环境

  OS windows Server

  Web Server: jakarta tomcat

  DataBase Server: MS SQL Server (打了SP3补丁)

  IDE: Eclipse +MyEclipse GA

  测试案例系统结构

  web层< >Service层< >DAO层

  web层使用struts DAO使用的spring的JDBC spring版本

  数据库中有两张表

  student 和Student 表结构相同 id name address.其中id为主键且为自增长型

  student 表中有一条记录

  id  name       address

      xiaoming    wuhan

  student 表中记录为空

  测试情形一

  web层捕获异常并处理 DAO层不捕获异常 Service也不捕获异常.

  Service层接口

  public interface StudentManagerService {

  public void  bus_method();

  }

  DAO层接口

  public interface StudentDAO {

  public void  deleteStudent ();

  public void  insertStudent ();

  }

  StudentDAO接口的实现

  public class StudentDAOImp extends JdbcDaoSupport implements StudentDAO{

  //删除student 表中的id= 的记录

  public void  deleteStudent (){

  JdbcTemplate jt=this getJdbcTemplate();

  jt update( delete from student where id= );

  }

  //将student 表中删除的记录插入到student 中 但是此方法实现有错 因为

  //id字段设置为自增长的 所以在插入记录时我们不能指定值

  public void  insertStudent (){

  JdbcTemplate jt=this getJdbcTemplate();

  String arg[]=new String[ ];

  arg[ ]= ;

  arg[ ]= xiaoming ;

spring事务实现方式 spring是如何对Service进行事务管理的

  arg[ ]= wuhan ;

  jt update( insert student (id name address) values(? ? ?) arg);

  }

  }

  StudentManagerService 接口的实现

  public class StudentManagerServiceImp implements StudentManagerService{

  private StudentDAO  stdDAO;

  public void setStdDAO(StudentDAO   stdDAO){

  this stdDAO=stdDAO;

  }

  //此方法为事务型的 删除student 中的记录成功且插入student 的记录也成功

  //如果insertStudent ()方法执行失败 那么deleteStudent ()方法也应该会失败

  public void  bus_method(){

  this stdDAO deleteStudent ();

  this stdDAO insertStudent ();

  }

  }

  web层:

  三个jsp 一个action:

  index jsp ==>首页面.上面仅仅有一个超链接<a herf= test do >执行</a>

  chenggong jsp ==>Service执行成功后转向的JSP页面

  shibai jsp ====>Service执行失败后转向的JSP页面

  action实现

  public class StudentManagerAction  extends  Action{

  public ActionForward execute(ActionMapping mapping ActionForm form

  HttpServletRequest request HttpServletResponse response) {

  try{

  WebApplicationContext appContext=WebApplicationContextUtils

  getWebApplicationContext(this getServlet() getServletContext());

  StudentManagerService stdm=(StudentManagerService)appContext

  getBean( stdServiceManager );

  stdm bus_method();

  return mapping findForward( chenggong );

  }

  catch(DataAccessException e){

  System err println( action execute service exception! );

  return mapping findForward( shibai );

  }

  }

  }

  配置文件

  web xml

  <?xml version= encoding= UTF ?>

  <web app xmlns= xmlns:xsi= instance version= xsi:schemaLocation= ;  app_ _ xsd >

  <context param>

  <param name>log jConfigLocation</param name>

  <param value>/WEB INF/log j properties</param value>

  </context param>

  <context param>

  <param name>contextConfigLocation</param name>

  <param value>/WEB INF/applicationContext xml</param value>

  </context param>

  <listener>

  <listener class> springframework web util Log jConfigListener</listener class>

  </listener>

  <listener>

  <listener class> sprntext ContextLoaderListener</listener class>

  </listener>

  <servlet>

  <servlet name>action</servlet name>

  <servlet class> apache struts action ActionServlet</servlet class>

  <init param>

  <param name>config</param name>

  <param value>/WEB INF/struts config xml</param value>

  </init param>

  <init param>

  <param name>debug</param name>

  <param value> </param value>

  </init param>

  <init param>

  <param name>detail</param name>

  <param value> </param value>

  </init param>

  <load on startup> </load on startup>

  </servlet>

  <servlet mapping>

  <servlet name>action</servlet name>

  <url pattern>* do</url pattern>

  </servlet mapping>

  </web app>

  sturts config xml

  <struts config>

  <action mappings >

  <action  input= /index jsp   path= /test   type= test StudentManagerAction   >

  <forward name= chenggong path= /chenggong jsp />

  <forward name= shibai path= /shibai jsp />

  </action>

  </action mappings>

  <message resources parameter= test ApplicationResources />

  </struts config>

  applicationContext xml

  <?xml version= encoding= UTF ?>

  <!DOCTYPE beans PUBLIC //SPRING//DTD BEAN//EN beans dtd >

  <beans>

  <bean id= dataSource

  class= mons dbcp BasicDataSource destroy method= close >

  <property name= driverClassName value= microsoft jdbc sqlserver SQLServerDriver ></property>

  <property name= url value= jdbc:microsoft:sqlserver:// : ;databasename=test ></property>

  <property name= username value= sa ></property>

  <property name= password value= sa ></property>

  </bean>

  <bean id= transactionManager class= springframework jdbc datasource DataSourceTransactionManager >

  <property name= dataSource ref= dataSource />

  </bean>

  <bean id= baseTxProxy class= springframework transaction interceptor TransactionProxyFactoryBean   lazy init= true >

  <property name= transactionManager >

  <ref bean= transactionManager />

  </property>

  <property name= transactionAttributes >

  <props>

  <prop key= * >PROPAGATION_REQUIRED</prop>

  </props>

  </property>

  </bean>

  <bean id= stdServiceManager   parent= baseTxProxy >

  <property name= target >

  <bean class= test StudentManagerServiceImp >

  <property name= stdDAO >

  <ref bean= stdDAO />

  </property>

  </bean>

  </property>

  </bean>

  <bean id= stdDAO class= test StudentDAOImp >

  <property name= dataSource ref= dataSource />

  </bean>

  </beans>

  运行程序 启动服务器 并部署.进入index jsp页面 点击 执行 超链接 >页面跳向shibai jsp

  查看控制台 打印有 action execute service exception!

  查看数据库  student 表中的[ xiaoming wuhan] 记录仍然存在 student 表仍然为空.

  小结 如果DAO层和Service不捕获异常而在web层捕获异常 web成功捕获异常 spring事务管理成功!

  测试情形二

  web层捕获异常并处理 Service捕获异常并处理 DAO层不捕获异常.

  修改StudentManagerServiceImp类

  public class StudentManagerServiceImp implements StudentManagerService{

  private StudentDAO  stdDAO;

  public void setStdDAO(StudentDAO   stdDAO){

  this stdDAO=stdDAO;

  }

  //此方法为事务型的 删除student 中的记录成功且插入student 的记录也成功

  //如果insertStudent ()方法执行失败 那么deleteStudent ()也应该会失败

  public void  bus_method(){

  try{

  this stdDAO deleteStudent ();

  this stdDAO insertStudent ();

  }

  catch(DataAccessException de)

  System err println( service execute exception! );

  }

  }

  }

  运行程序 启动服务器 并部署.进入index jsp页面 点击 执行 超链接 >页面跳向chenggong jsp

  查看控制台 打印有 service execute exception!

  查看数据库  student 表中的[ xiaoming wuhan] 记录不存在 student 表仍然为空.

  小结 如果Service捕获异常并处理而不向外抛出 web层捕获不到异常 spring事务管理失败!

  测试情形(还原表中的数据)三

  web层捕获异常 Service捕获异常 DAO层也捕获异常.

  修改StudentDAOImp类代码

  public class StudentDAOImp extends JdbcDaoSupport implements StudentDAO{

  //删除student 表中的id= 的记录

  public void  deleteStudent (){

  try{

  JdbcTemplate jt=this getJdbcTemplate();

  jt update( delete from student where id= );

  }

  catch(DataAccessException e){

  System err println( dao deleteStudent  execute exception! );

  }

  }

  //将student 表中删除的记录插入到student 中 但是此方法实现有错 因为

  //id字段设置为自增长的 所以在插入记录时我们不能指定值

  public void  insertStudent (){

  try{

  JdbcTemplate jt=this getJdbcTemplate();

  String arg[]=new String[ ];

  arg[ ]= ;

  arg[ ]= xiaoming ;

  arg[ ]= wuhan ;

  jt update( insert student (id name address) values(? ? ?) arg);

  }

  catch(DataAccessException  e){

  System err println( dao insertStudent   execute exception! );

  }

  }

  }

  运行程序 启动服务器 并部署.进入index jsp页面 点击 执行 超链接 >页面跳向chenggong jsp

  查看控制台 打印有 dao insertStudent execute exception!

  查看数据库  student 表中的 xiaoming wuhan 记录不存在 student 表仍然为空.

  小结如果DAO的每一个方法自己捕获异常并处理而不向外抛出 Service层捕获不到异常 Web层同样捕获不到异常 spring事务管理失败!

  测试情形四

  还原数据库中的数据

  还原StudentDAOImp类中的方法为测试情形一中的实现

  web层捕获异常Service抛出的自定义异常StudentManagerException

  Service捕获DataAccessException并抛出StudentManagerException

  StudentManagerException为DataAccessException的子类

  DAO层不捕获异常

  修改StudentManagerServiceImp类的实现

  public class StudentManagerServiceImp implements StudentManagerService{

  private StudentDAO  stdDAO;

  public void setStdDAO(StudentDAO   stdDAO){

  this stdDAO=stdDAO;

  }

  //此方法为事务型的 删除student 中的记录成功且插入student 的记录也成功

  //如果insertStudent ()方法执行失败 那么deleteStudent ()也应该会失败

  public void  bus_method() throws StudentManagerException{

  try{

  this stdDAO deleteStudent ();

  this stdDAO insertStudent ();

  }

  catch(DataAccessException de)

  System err println( service execute exception! );

  throw new StudentManagerException();//StudentManagerException类继承DataAcce                          //ssException异常

  }

  }

  }

  修改StudentManagerAction

  public class StudentManagerAction  extends  Action{

  public ActionForward execute(ActionMapping mapping ActionForm form

  HttpServletRequest request HttpServletResponse response) {

  try{

  WebApplicationContext appContext=WebApplicationContextUtils

  getWebApplicationContext(this getServlet() getServletContext());

  StudentManagerService stdm=(StudentManagerService)appContext

  getBean( stdServiceManager );

  stdm bus_method();

  return mapping findForward( chenggong );

  }

  catch(StudentManagerException e){

  System err println( action execute service exception! );

  return mapping findForward( shibai );

  }

  }

  }

  运行程序 启动服务器 并部署.进入index jsp页面 点击 执行 超链接 >页面跳向shibai jsp

  查看控制台 打印有 service execute exception!

  action execute service exception!

  查看数据库  student 表中的 [ xiaoming wuhan] 记录仍然存在 student 表仍然为空.

  小结如果DAO的每一个方法不捕获异常 Service层捕获DataAccessException异常并抛出自己定义异常(自定义异常为DataAccessException的子类) Web层可以捕获到异常 spring事务管理成功!

  结合源码总结

   spring在进行声明时事务管理时 通过捕获Service层方法的DataAccessException来提交和回滚事务的 而Service层方法的DataAccessException又是来自调用DAO层方法所产生的异常.

   我们一般在写DAO层代码时 如果继承JdbcDaoSupport 类 并使用此类所实现的JdbcTemplate来执行数据库操作 此类会自动把低层的SQLException转化成DataAccessException以及DataAccessException

  的子类.

lishixinzhi/Article/program/Java/ky/201311/28430  
永远跟党走
  • 如果你觉得本站很棒,可以通过扫码支付打赏哦!

    • 微信收款码
    • 支付宝收款码