首页 > 代码库 > Spring4+Hibernate4 事务管理 配置 注解 AOP

Spring4+Hibernate4 事务管理 配置 注解 AOP

在单独使用hibernate的时候

使用如下配置:

<property name="hibernate.current_session_context_class">thread</property>

根据文档,这个是hibernate3.1以后的一个新扩展,目的在于可以让我们在某一个上下文环境(比如说当前线程)中可以通过SessionFactory.getCurrentSession()得到同一个session会话. 
该方式hibernate会自动关闭session,但是事务控制仍然需要手动开始和提交。

public Long createUser(UserVO user) {
        Session session = sessionFactory.getCurrentSession();
        Transaction tx = session.beginTransaction();
        Long id = (Long) session.save(user);
        tx.commit();
        return id;
    }

在Spring + Hibernate 整合时

我们希望通过 spring 使用声明式事务管理 或使用@Transactional注解进行事务管理。 
如果 hibernate.current_session_context_class 属性配置为thread话,会抛一个异常: get is not valid without active transaction。这个错误一般情况是因为由getCurrentSession得到的session中没有获得的transaction,我们一般要手动的调用Transaction tx = session.beginTransaction(); 和 tx.commit() 来控制事务。但是问题是,我们在spring的配置文件中不是已经通过aop,指定了此处由spring来管理事务吗,怎么还要手动处理事务?

解决办法是将 thread 改为 org.springframework.orm.hibernate4.SpringSessionContext。

<property name="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</property>

其实这就是默认值,把这段配置去掉,也是可以调用 sessionFactory.getCurrentSession(),以及使用 Spring 进行事务管理。

下面提我的配置和代码,经过测试ok。

pom.xml–项目jar包依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.taj.test</groupId>
    <artifactId>hibernate-test</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.3.11.Final</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>

        <!-- AOP -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.7</version>
        </dependency>
        <!-- AOP -->

        <!-- 测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <!-- Oracle的驱动包 -->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc14</artifactId>
            <version>10.2.0.4.0</version>
        </dependency>
    </dependencies>
</project>

技术分享

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"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">



    <context:component-scan base-package="com.taj.**.dao" />
    <context:component-scan base-package="com.taj.**.service" />

    <!-- 数据源配置 -->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value=http://www.mamicode.com/"oracle.jdbc.driver.OracleDriver" />
        <property name="url" value=http://www.mamicode.com/"jdbc:oracle:thin:@localhost:1521:XE" />
        <property name="username" value=http://www.mamicode.com/"ssh" />
        <property name="password" value=http://www.mamicode.com/"ssh" />
    </bean>

    <!-- session工厂 -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value=http://www.mamicode.com/"classpath:hibernate.cfg.xml" />
        <property name="mappingDirectoryLocations">
            <list>
                <value>classpath:com/taj/**/model</value>
            </list>
        </property>
    </bean>

    <!-- 事务管理器 -->
    <bean id="txManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- 开启通过注解@Transactional管理事务 -->
    <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />

    <!-- 事务 -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="query*" read-only="true" propagation="REQUIRED" />
            <tx:method name="find*" read-only="true" propagation="REQUIRED" />
            <tx:method name="*" propagation="REQUIRED" />
        </tx:attributes>
    </tx:advice>

    <!-- 配置AOP -->
    <aop:config proxy-target-class="true">
        <aop:pointcut expression="execution(* *..service..*Service*.*(..))" id="serviceMethod" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />
    </aop:config>
</beans>

 

hibernate.cfg.xml

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="show_sql">true</property>
        <!-- 
        <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <property name="hibernate.connection.username">ssh</property>
        <property name="hibernate.connection.password">ssh</property>
        <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:XE</property>
         -->
        <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>

        <!-- Hibernate的session管理:自动管理:"jta", "thread", and "managed". -->
        <!-- 默认为:org.springframework.orm.hibernate4.SpringSessionContext-->
        <!-- 默认时,除了手动管理,还可以交给Spring管理事务和关闭session(aop配置或注解实现) -->
        <!-- 
        <property name="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</property>
         -->
        <!-- 
        <mapping resource="com/taj/sshall/user/model/UserVO.hbm.xml"/>
        -->

    </session-factory>
</hibernate-configuration>

userDao

package com.taj.sshall.user.dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.taj.sshall.user.model.UserVO;

@Component(value=http://www.mamicode.com/"userDao")
public class UserDaoSpringHibernateImpl extends UserDaoHibernateImpl {

    @Autowired
    @Override
    public void setSessionFactory(SessionFactory sessionFactory){
        super.setSessionFactory(sessionFactory);
    }

    /**
     * sessionFactory.getCurrentSession()
     * 1. Hibernate 自动管理,thread方式实现。session自动关闭,但是需要手动开启和关闭事务。
     *    <property name="current_session_context_class">thread</property>
     * 2. Spring 自动管理,通过AOP或注解@Transactional实现。session和事务都自动管理。
     *    <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />
     */
    @Override
    //@Transactional
    public Long createUser(UserVO user) {
        Session session = sessionFactory.getCurrentSession();
        //Transaction tx = session.beginTransaction();
        Long id = (Long) session.save(user);
        //tx.commit();
        return id;
    }
}

 

UserDaoHibernateImpl.Java

package com.taj.sshall.user.dao;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Example;
import com.taj.sshall.common.page.PageVO;
import com.taj.sshall.user.model.UserVO;
public class UserDaoHibernateImpl implements IUserDao {

    public SessionFactory sessionFactory;

    public List<UserVO> findUserPage(UserVO user, PageVO page) {
        //q_user_all
        Session session = sessionFactory.openSession();
        //Query query = session.getNamedQuery("q_user_all");
        Criteria criteria = session.createCriteria(UserVO.class);
        criteria.add(Example.create(user));
        criteria.setFirstResult((page.getPage()-1) * page.getSize());
        criteria.setMaxResults(page.getPage() * page.getSize());

        @SuppressWarnings("unchecked")
        List<UserVO> list = criteria.list();
        return list;
    }

    public List<UserVO> findUsersByName(String userName) {
        Session session = sessionFactory.openSession();

        String hql = "from UserVO u where u.userName=?1";
        Query query = session.createQuery(hql);
        query.setString("1", userName);

        @SuppressWarnings("unchecked")
        List<UserVO> list = query.list();
        return list;
    }

    public UserVO findUserById(Long userId) {
        Session openSession = sessionFactory.openSession();
        UserVO user = (UserVO)openSession.get(UserVO.class, userId);
        openSession.close();
        return user;
    }

    public Long createUser(UserVO user) {
        Session openSession = sessionFactory.openSession();
        Transaction tx = openSession.beginTransaction();
        Long id = (Long) openSession.save(user);
        tx.commit();
        openSession.close();
        return id;
    }

    public void updateUser(UserVO user) {
        Session openSession = sessionFactory.openSession();
        Transaction tx = openSession.beginTransaction();
        openSession.update(user);
        tx.commit();
        openSession.close();
    }

    public void deleteUser(UserVO user) {
        Session openSession = sessionFactory.openSession();
        Transaction tx = openSession.beginTransaction();
        openSession.delete(user);
        tx.commit();
        openSession.close();
    }

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
}

 

userService

package com.taj.sshall.user.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.taj.sshall.user.dao.IUserDao;
import com.taj.sshall.user.model.UserVO;

@Component("userService")
public class UserServiceSpringImpl implements IUserService {

    @Autowired
    private IUserDao userDao;

    public Long createUser(UserVO user) {
        Long createUser = userDao.createUser(user);
        return createUser;
    }
    ----------- 省略其他方法 -----------
}

SSHUtils.java

package com.taj.sshall.common;
import java.util.Arrays;
import java.util.Properties;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SSHUtils {

    private static ThreadLocal<SessionFactory> sessionFactoryLocal;
    private static ThreadLocal<ApplicationContext> applicationContextLocal;

    public static SessionFactory getSessionFactory(){
        if(sessionFactoryLocal == null){
            Configuration cfg = new Configuration().configure();
            Properties settings = cfg.getProperties();
            ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                    .applySettings(settings).build();
            SessionFactory sf = cfg.buildSessionFactory(serviceRegistry);
            sessionFactoryLocal = new ThreadLocal<SessionFactory>();
            sessionFactoryLocal.set(sf);
        }
        return sessionFactoryLocal.get();
    }
    public static ApplicationContext getAppContext(){
        if(applicationContextLocal == null){
            ApplicationContext context = newClassPathXmlApplicationContext("applicationContext.xml");
            applicationContextLocal = new ThreadLocal<ApplicationContext>();
            applicationContextLocal.set(context);
        }
        return applicationContextLocal.get();
    }
    public static void main(String[] args) {
        //测试sessionFactory
        SessionFactory sessionFactory = getSessionFactory();
        Session openSession = sessionFactory.openSession();
        System.out.println(openSession);
        openSession.close();

        //测试appContext
        ApplicationContext appContext = getAppContext();
        String[] names = appContext.getBeanDefinitionNames();
        System.out.println(Arrays.toString(names));
    }
}

 

UserServiceSpringImplTest.java –(用Junit进行测试)

package com.taj.sshall.user.service;
import static org.junit.Assert.*;
import java.util.Date;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import com.taj.sshall.common.SSHUtils;
import com.taj.sshall.user.model.UserVO;

public class UserServiceSpringImplTest {
    private static IUserService userService;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        ApplicationContext appContext = SSHUtils.getAppContext();
        userService = (IUserService) appContext.getBean("userService");
    }

    @Test
    public void testCreateUser() {
        UserVO user = new UserVO();
        user.setUserName("test_");
        user.setPassword("1234567");
        user.setAge(30);
        user.setEmail("test_@126.com");
        user.setCreateDate(new Date());
        user.setLastUpdateDate(new Date());

        Long id = userService.createUser(user);
        assertTrue(id != null);
    }
}

UserDaoHibernateImplTest.java –(用Junit进行测试)

package com.taj.sshall.user.dao;

import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.taj.sshall.common.SSHUtils;
import com.taj.sshall.common.page.PageVO;
import com.taj.sshall.user.model.UserVO;

public class UserDaoHibernateImplTest {

    public IUserDao userDao;
    public SessionFactory sessionFactory;

    @Before
    public void before() throws Exception {
        UserDaoHibernateImpl dao = new UserDaoHibernateImpl();
        dao.setSessionFactory(SSHUtils.getSessionFactory());
        this.userDao = dao;
        this.sessionFactory = dao.getSessionFactory();
    }

    @Test
    public void testFindUserPage() {
        UserVO user = new UserVO();
        user.setEmail("test@126.com");
        PageVO page = new PageVO();

        for (int i = 1; i <= 5; i++) {
            page.setPage(i);
            List<UserVO> lst = userDao.findUserPage(user, page);
            System.out.println(Arrays.toString(lst.toArray()));
            System.out.println("----------------------------------------------\n");
        }

    }

    @Test
    public void findUsersByName() {
        List<UserVO> users = userDao.findUsersByName("test_0");
        for (UserVO userVO : users) {
            System.out.println("{" + userVO.getUserId() + ", "
                    + userVO.getUserName() + ", " + userVO.getEmail() + "}");
        }
    }

    @Test
    public void testFindUserById() {
        Long userId = 10000L;
        UserVO user = userDao.findUserById(userId);

        assertTrue("tajun77".equals(user.getUserName()));
        assertTrue("123456".equals(user.getPassword()));
        assertTrue("tajun77@126.com".equals(user.getEmail()));
        assertTrue(27 == user.getAge());
    }

    @Test
    public void testCreateUser() {
        for (int i = 0; i < 25; i++) {
            UserVO user = new UserVO();
            user.setUserName("test_"+i);
            user.setPassword("1234567");
            user.setAge(30);
            user.setEmail("test@126.com");
            user.setCreateDate(new Date());
            user.setLastUpdateDate(new Date());

            Long id = userDao.createUser(user);
            assertTrue(id != null);
        }
    }

    @Test
    public void testUpdateUser() {
        UserVO user = userDao.findUserById(10001L);
        int age = (user.getAge() + 7) % 30 + 20;
        user.setAge(age);
        userDao.updateUser(user);

        UserVO user2 = userDao.findUserById(10001L);
        assertTrue(user2.getAge() == age);
    }

    @Test
    public void testDeleteUser() {
        UserVO user = userDao.findUserById(10000L);
        user.setUserName("testDelete");
        Long id = userDao.createUser(user);

        UserVO u_have = userDao.findUserById(id);
        assertTrue(u_have != null);

        UserVO udel = new UserVO();
        udel.setUserId(id);
        userDao.deleteUser(udel);// userName=test id=10003

        UserVO u_no = userDao.findUserById(id);
        assertTrue(u_no == null);
    }

    @After
    public void after() throws Exception {
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();
        Query query = session.createQuery("delete from UserVO u where u.userId > 10122");
        query.executeUpdate();
        tx.commit();
        session.close();
    }
}
 

Spring4+Hibernate4 事务管理 配置 注解 AOP