• spring aop 声明式事务管理


    Spring使用AOP来完成声明式的事务管理   有annotation和xml两种形式

    代码和上一篇基本相近,再贴一遍

    两个实体类

    package com.ouc.wkp.model;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    
    @Entity(name = "t_log")
    public class Log {
        private int id;
        private String msg;
    
        @Id
        @GeneratedValue
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
    }
    Log.java
    package com.ouc.wkp.model;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    
    @Entity(name="user2")
    public class User2 {
        private int id;
        private String username;
    
        @Id
        @GeneratedValue
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        @Column
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
    }
    User2.java

    两个接口DAO

    package com.ouc.wkp.dao;
    
    import com.ouc.wkp.model.Log;
    
    public interface LogDAO {
        public void save(Log log);
    }
    LogDAO.java
    package com.ouc.wkp.dao;
    
    import com.ouc.wkp.model.User2;
    
    public interface UserDAO {
        public void save(User2 user2);
        public void delete();
    }
    UserDAO.java

    接口实现

    package com.ouc.wkp.dao.impl;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    
    import javax.annotation.Resource;
    import javax.sql.DataSource;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.springframework.stereotype.Component;
    
    import com.ouc.wkp.dao.UserDAO;
    import com.ouc.wkp.model.User2;
    
    @Component("u")
    public class UserDAOImpl implements UserDAO {
    
        // private DataSource dataSource;
        //
        // public DataSource getDataSource() {
        // return dataSource;
        // }
        //
        // @Resource
        // public void setDataSource(DataSource dataSource) {
        // this.dataSource = dataSource;
        // }
    
        private SessionFactory sessionFactory;
    
        public SessionFactory getSessionFactory() {
            return sessionFactory;
        }
    
        @Resource
        public void setSessionFactory(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }
    
        @Override
        public void save(User2 user2) {
            // Hibernate
            // JDBC
            // XML
            // NetWork
    //        System.out
    //                .println("session factory class:" + sessionFactory.getClass());
            Session s = sessionFactory.getCurrentSession();
    //        s.beginTransaction();
            s.save(user2);
    //        s.getTransaction().commit();
    //        System.out.println("user saved!");
    
        }
    
        @Override
        public void delete() {
            // TODO Auto-generated method stub
    
        }
    
    }
    UserDAOImpl.java
    package com.ouc.wkp.dao.impl;
    
    import javax.annotation.Resource;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.springframework.stereotype.Component;
    
    import com.ouc.wkp.dao.LogDAO;
    import com.ouc.wkp.model.Log;
    
    @Component("logDAO")
    public class LogDAOImpl implements LogDAO {
    
        private SessionFactory sessionFactory;
    
        public SessionFactory getSessionFactory() {
            return sessionFactory;
        }
    
        @Resource
        public void setSessionFactory(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }
        
        @Override
        public void save(Log log) {
            Session s = sessionFactory.getCurrentSession();
            s.save(log);
    //        throw new RuntimeException();//事务会回滚   spring配置后省去了try catch
        }
    
    }
    LogDAOImpl.java
    package com.ouc.wkp.service;
    
    import javax.annotation.Resource;
    
    import org.springframework.stereotype.Component;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.ouc.wkp.dao.LogDAO;
    import com.ouc.wkp.dao.UserDAO;
    import com.ouc.wkp.model.Log;
    import com.ouc.wkp.model.User2;
    
    @Component("userService")
    public class UserService {
    
        private UserDAO userDAO;
        private LogDAO logDAO;
    
        public LogDAO getLogDAO() {
            return logDAO;
        }
    
        @Resource(name = "logDAO")
        public void setLogDAO(LogDAO logDAO) {
            this.logDAO = logDAO;
        }
    
        public User2 getUser(int id) {
            return null;
        }
    
        public void init() {
            System.out.println("init");
        }
    
    //    @Transactional(propagation = Propagation.REQUIRED)
        // 事务的传播特性 默认REQUIRED
        // readOnly=true只读的 spring会进行优化
        // 声明式事务管理 进行事务
        public void add(User2 user2) {
            userDAO.save(user2);
            Log log = new Log();
            log.setMsg("a user saved");
            logDAO.save(log);
        }
    
        public UserDAO getUserDAO() {
            return userDAO;
        }
    
        @Resource(name = "u")
        public void setUserDAO(UserDAO userDAO) {
            this.userDAO = userDAO;
        }
    
        public void destroy() {
            System.out.println("destroy");
        }
    }
    UserService.java

    使用注解时在对应的方法前加上@Transactional(propagation = Propagation.REQUIRED)

    (propagation = Propagation.REQUIRED)可以省去,因为事务的传播特性 默认为REQUIRED

    配置文件

      1 <?xml version="1.0" encoding="UTF-8"?>
      2 <beans xmlns="http://www.springframework.org/schema/beans"
      3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
      4     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
      5     xsi:schemaLocation="http://www.springframework.org/schema/beans
      6             http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
      7             http://www.springframework.org/schema/context
      8             http://www.springframework.org/schema/context/spring-context-3.1.xsd
      9             http://www.springframework.org/schema/aop
     10             http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
     11             http://www.springframework.org/schema/tx 
     12            http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
     13     <context:annotation-config />
     14     <!-- 使用注解需要下面四条 -->
     15     <!-- xmlns:context="http://www.springframework.org/schema/context" -->
     16     <!-- http://www.springframework.org/schema/context -->
     17     <!-- http://www.springframework.org/schema/context/spring-context-3.1.xsd"> -->
     18     <!-- <context:annotation-config /> -->
     19 
     20     <!-- 使用aop需要一下 -->
     21     <!-- xmlns:aop="http://www.springframework.org/schema/aop" -->
     22     <!-- http://www.springframework.org/schema/aop -->
     23     <!-- http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> -->
     24     <!-- <aop:aspectj-autoproxy /> -->
     25 
     26     <!-- 使用事务 -->
     27     <!-- xmlns:tx="http://www.springframework.org/schema/tx" -->
     28     <!-- http://www.springframework.org/schema/tx -->
     29     <!-- http://www.springframework.org/schema/tx/spring-tx-2.5.xsd -->
     30     <!-- <tx:annotation-driven transaction-manager="txManager"/> -->
     31 
     32 
     33     <!-- 扫描 -->
     34     <context:component-scan base-package="com.ouc.wkp"></context:component-scan>
     35 
     36     <aop:aspectj-autoproxy />
     37 
     38     <bean
     39         class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
     40         <property name="locations">
     41             <value>classpath:jdbc.properties</value>
     42         </property>
     43     </bean>
     44 
     45     <bean id="dataSource" destroy-method="close"
     46         class="org.apache.commons.dbcp.BasicDataSource">
     47         <property name="driverClassName" value="${jdbc.driverClassName}" />
     48         <property name="url" value="${jdbc.url}" />
     49         <property name="username" value="${jdbc.username}" />
     50         <property name="password" value="${jdbc.password}" />
     51     </bean>
     52 
     53     <bean id="sessionFactory"
     54         class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
     55         <property name="dataSource" ref="dataSource" />
     56         <!-- <property name="annotatedClasses"> -->
     57         <!-- <list> -->
     58         <!-- <value>com.ouc.wkp.model.User2</value> -->
     59         <!-- <value>com.ouc.wkp.model.Log</value> -->
     60         <!-- </list> -->
     61         <!-- </property> -->
     62         <property name="packagesToScan">
     63             <list>
     64                 <value>com.ouc.wkp.model</value>
     65             </list>
     66         </property>
     67         <property name="hibernateProperties">
     68             <props>
     69                 <prop key="hibernate.dialect">
     70                     org.hibernate.dialect.MySQLDialect
     71                 </prop>
     72                 <prop key="hibernate.show_sql">true</prop>
     73             </props>
     74         </property>
     75     </bean>
     76 
     77 
     78     <!-- Spring使用AOP来完成声明式的事务管理 -->
     79     <bean id="txManager"
     80         class="org.springframework.orm.hibernate4.HibernateTransactionManager">
     81         <!-- <property name="dataSource" ref="dataSource" /> -->
     82         <property name="sessionFactory" ref="sessionFactory" />
     83     </bean>
     84 
     85     <tx:annotation-driven transaction-manager="txManager" />
     86 
     87     <aop:config>
     88         <aop:pointcut expression="execution(public * com.ouc.wkp.service..*.*(..))"
     89             id="businessService" />
     90         <!-- 在此pointcut上加上txAdvice建议 -->
     91         <aop:advisor advice-ref="txAdvice" pointcut-ref="businessService" />
     92     </aop:config>
     93 
     94     <tx:advice id="txAdvice" transaction-manager="txManager">
     95         <tx:attributes>
     96             <tx:method name="getUser" read-only="true" />
     97             <tx:method name="add*" propagation="REQUIRED" />
     98         </tx:attributes>
     99     </tx:advice>
    100 
    101 </beans>
    beans.xml

    两个地方需要注意

    1.这种方式可以省去写多个model类的配置

    <property name="packagesToScan">
      <list>
        <value>com.ouc.wkp.model</value>
      </list>
    </property>

    2.

    bean定义了一个事务管理,注入sessionFactory。

    紧接着规定事务管理器为txManager即上面bean中定义的。

    <aop:config>定义一个切面,在这个切面加上advice。

    最后定义一个advice,

    <tx:method name="getUser" read-only="true" />表示getUser方法是只读的并且进行了声明式事务管理。readonly可以提高程序效率。

    <tx:method name="add*" propagation="REQUIRED" />标识为以add开头的方法添加事务。

    测试类

    package com.ouc.wkp.test;
    
    import org.junit.Test;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.ouc.wkp.model.User2;
    import com.ouc.wkp.service.UserService;
    
    //Dependency Injection
    //Inverse of Control
    public class UserServiceTest {
    
        @Test
        public void testAdd() throws Exception {
            ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
                    "beans.xml");
    
            UserService service = (UserService) ctx.getBean("userService");
            User2 user2=new User2();
            user2.setId(1);
            user2.setUsername("ttyy");
            System.out.println(user2);
            service.add(user2);
    
            ctx.destroy();
    
        }
    
    }
    UserServiceTest.java

    如果出错则事务回滚,两条记录都增加失败。

  • 相关阅读:
    【排序】快速排序代码实现及优化
    【SpringMVC】重定向和转发
    RESTful风格
    【SpringMVC】用demo了解执行流程(xml配置)
    【Spring】声明式事务aop
    【Spring】整合Mybatis两种方式
    MongoDB语法与现有关系型数据库SQL语法比较
    Oracle查看哪些表被锁住了
    Mongodb分布式集群搭建
    四大MQ比较及MQ详解
  • 原文地址:https://www.cnblogs.com/wangkaipeng/p/5782116.html
Copyright © 2020-2023  润新知