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

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

 

posted @ 2016-08-17 22:08  docyard  阅读(8791)  评论(0编辑  收藏  举报