zoukankan      html  css  js  c++  java
  • @Transactional 注解的使用和注意

    转载:http://epine.itpub.net/post/8159/526281

    1. 在需要事务管理的地方加@Transactional 注解。@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上

    2. @Transactional 注解只能应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。

    3. 注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅 是一种元数据。必须在配置文件中使用配置元素,才真正开启了事务行为。

    4. 通过 元素的 "proxy-target-class" 属性值来控制是基于接口的还是基于类的代理被创建。如果 "proxy-target-class" 属值被设置为 "true",那么基于类的代理将起作用(这时需要CGLIB库cglib.jar在CLASSPATH中)。如果 "proxy-target-class" 属值被设置为 "false" 或者这个属性被省略,那么标准的JDK基于接口的代理将起作用。


    标准的JDK基于接口的代理将起作用-->
    proxy-target-class="false"/>

    基于类的代理将起作用 ,同时 cglib.jar必须在CLASSPATH中
    proxy-target-class="true"/>
    -->


    非JTA事务(即非分布式事务), 事务配置的时候 ,需要指定dataSource属性(非分布式事务,事务是在数据库创建的链接上开启。)-->


    JTA事务(非分布式事务), 事务配置的时候 ,不能指定dataSource属性(分布式事务,是有全局事务来管理数据库链接的)-->

    解@Transactional cglib与java动态代理最大区别是代理目标对象不用实现接口,那么注解要是写到接口方法上,要是使用cglib代理,这是注解事物就失效了,为了保持兼容注解最好都写到实现类方法上。

    5. Spring团队建议在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。在接口上使用 @Transactional 注解,只能当你设置了基于接口的代理时它才生效。因为注解是 不能继承 的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装。

    6. @Transactional 的事务开启 ,或者是基于接口的 或者是基于类的代理被创建。所以在同一个类中一个方法调用另一个方法有事务的方法,事务是不会起作用的

    public interface PersonService {
    //删除指定id的person
    public void delete(Integer personid) ;

    //删除指定id的person,flag
    public void delete(Integer personid,boolean flag) ;
    }

    public class PersonServiceBean implements PersonService {
    private JdbcTemplate jdbcTemplate;

    public void delete(Integer personid){
    try{
    this.delete(personid,true)
    System.out.println("delete success");
    }catch(Exception e){
    System.out.println("delete failed");
    }
    }

    @Transactional
    //此时,事务根本就没有开启, 即数据库会默认提交该操作,即记录别删除掉
     public void delete(Integer personid,boolean flag){
    if(flag == ture){
    jdbcTemplate.update("delete from person where id=?", new Object[]{personid},
    new int[]{java.sql.Types.INTEGER});
    throw new RuntimeException("运行期例外");
    }
    }
    }

    public class PersonServiceBeanTest{
    PersonService ps = new PersonServiceBean ();
    ps.delete(5);
    }

    7. Spring使用声明式事务处理,默认情况下,如果被注解的数据库操作方法中发生了unchecked异常,所有的数据库操作将rollback;如果发生的异常是checked异常,默认情况下数据库操作还是会提交的。

    -----------------------------------------------------------------------------------------------------------------------------------------------
    public interface PersonService {
    //删除指定id的person
    public void delete(Integer personid) ;

    //获取person
    public Person getPerson(Integer personid);
    }

    //PersonServiceBean 实现了PersonService 接口,则基于接口的还是基于类的代理 都可以实现事务
    @Transactional
     public class PersonServiceBean implements PersonService {
    private JdbcTemplate jdbcTemplate;

    //发生了unchecked异常,事务回滚, @Transactional
    public void delete(Integer personid){
    jdbcTemplate.update("delete from person where id=?", new Object[]{personid},
    new int[]{java.sql.Types.INTEGER});
    throw new RuntimeException("运行期例外");
    }
    }

    ---------------------------------------------------------------------------------------------------------------------------------------------------
    public interface PersonService {
    //删除指定id的person
    public void delete(Integer personid) throws Exception;

    //获取person
    public Person getPerson(Integer personid);
    }

    @Transactional
    public class PersonServiceBean implements PersonService {

    //发生了checked异常,事务不回滚,即数据库记录仍能被删除,
    //checked的例外,需要我们在外部用try/catch语法对调用该方法的地方进行包含
     @Transactional
    public void delete(Integer personid) throws Exception{
    jdbcTemplate.update("delete from person where id=?", new Object[]{personid},
    new int[]{java.sql.Types.INTEGER});
    throw new Exception("运行期例外");
    }

    }
    ---------------------------------------------------------------------------------------------------------------------------------------------------
    但是,对于checked这种例外,默认情况下它是不会进行事务回滚的,但是如果我们需要它进行事务回滚,这时候可以在delete方法上通过@Transaction这个注解来修改它的行为。

    @Transactional
    public class PersonServiceBean implements PersonService {

    @Transactional(rollbackFor=Exception.class)
    //rollbackFor这属性指定了,既使你出现了checked这种例外,那么它也会对事务进行回滚

    public void delete(Integer personid) throws Exception{
    jdbcTemplate.update("delete from person where id=?", new Object[]{personid},
    new int[]{java.sql.Types.INTEGER});
    throw new Exception("运行期例外");
    }
    }
    ---------------------------------------------------------------------------------------------------------------------------------------------------

    在PersonServiceBean这个业务bean里面,有一些事务是不需要事务管理的,好比说获取数据的getPersons方法,getPerson方法。因为@Transactional 放在了类的上面。


    此时,可以采用propagation这个事务属性@Transactional(propagation=Propagation.NOT_SUPPORTED),propagation这个属性指定了事务传播行为,我们可以指定它不支持事务,当我们这么写了之后,Spring容器在getPersons方法执行前就不会开启事务.

    @Transactional
    public class PersonServiceBean implements PersonService {

    @Transactional(propagation=Propagation.NOT_SUPPORTED)
    //则此方法 就不会开启事务了
    public Person getPerson(Integer personid)
    {
    }
    }

  • 相关阅读:
    sfs2x 连接 mongodb
    java websocket
    webstorm 4.0 注册码
    解决 sfs2 admin tool 找不到扩展
    window 注册表五大类
    opengl 学习第二日
    java google Protobuf
    扩展 java sencha touch PhonegapPlugin
    sencha touch2 kryonet socket phonegap 通信 作者:围城
    sencha touch2 layout 笔记
  • 原文地址:https://www.cnblogs.com/Loadhao/p/6553606.html
Copyright © 2011-2022 走看看