Spring整合hibernate -声明事务管理

 目录

1 sessionFactory 注入HibernateTransactionManager

2 XML配置的配置

3 添加annotation-driven

4 引入JAR包 

5在service层添加事务声明的注释

6 改写数据库的实现类的方法,不再需要开始事务和提交事务,并且使用getCurrentSession 

7 编写测试类通过 

通过Spring的事务管理可以实现,对事务的统一管理,并且写节省冗余代码,结构清晰 抓到runtimeException进行回滚,

事务的策略Springl默认是required

1 sessionFactory注入org.springframework.orm.hibernate4.HibernateTransactionManager

    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
            <property name="sessionFactory" ref="mySessionFactory"></property> 
    </bean>

2 引入XML配置

1 xmlns:tx="http://www.springframework.org/schema/tx"

2 http://www.springframework.org/schema/tx
3 http://www.springframework.org/schema/tx/spring-tx.xsd

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        ">

3 添加annotation-driven

<tx:annotation-driven transaction-manager="txManager" />

4 引入JAR包 

aopalliance-1.0  

5在service层添加事务声明的注释

    @Transactional
    public void add(User user) {
        userDao.save(user);
    }

6 改写数据库的实现类的方法,不再需要开始事务和提交事务,并且使用getCurrentSession

    public void save(User user) {
        System.out.println(user.getName()+"-->"+user.getRemark()+"  save --调用UserDaoImpl2!");
        Session s = mySessionFactory.getCurrentSession();
        s.save(user);
    }

7 测试一下

@Test
    public void testAdd() {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("beans.xml");
         UserServiceImpl UserServiceImpl = (UserServiceImpl)app.getBean("userServiceImpl");
         UserServiceImpl.add(user);//调用方法
    }

8 测试通过

下面会详细给出代码

9编译常见的报错信息

1  Add CGLIB to the class path or specify proxy interfaces.
引入 cglib-nodep-2.1_3.jar

   2 org.hibernate.HibernateException: save is not valid without active transaction
  去掉sessionFactory的property的配置 hibernate.current_session_context_class=thread

  3 org.hibernate.MappingException: Unknown entity: com.entity.Log

   sessionFactory里需要配置property的实体类

<property name="annotatedClasses">
            <list>
                <value>com.entity.User</value>
                <value>com.entity.Log</value>
            </list>
</property>

-------------------------------------------------------------------------------------------- 

Spring的事务管理具体的应用

例如 有一个服务service是完成以下功能

1 保存一个用户信息进A表,保存成功后打印一条日志进入B表

2 如果日志打印报错则插入的A表的用户回滚

完整的代码

 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:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        ">
        
        
        <context:component-scan base-package="com.*"></context:component-scan>
        <tx:annotation-driven transaction-manager="txManager" />
        
    <bean id="mappings"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <value>classpath:jdbc.properties</value>
        </property>
    </bean>
    
<!--    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">-->
<!--        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>-->
<!--        <property name="url" value="jdbc:mysql://localhost:3306/spring"/>-->
<!--        <property name="username" value="root"/>-->
<!--        <property name="password" value="root"/>-->
<!--    </bean>-->

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <bean id="mySessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">    
        <property name="dataSource" ref="dataSource" />
        <property name="annotatedClasses">
            <list>
                <value>com.entity.User</value>
                <value>com.entity.Log</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=org.hibernate.dialect.MySQLDialect
                hibernate.show_sql=true
<!--                hibernate.current_session_context_class=thread-->
            </value>
        </property>
    </bean>
    
    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
            <property name="sessionFactory" ref="mySessionFactory"></property> 
    </bean>
  
</beans>

service

package com.serviceImpl;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.dao.LogDao;
import com.dao.UserDao;
import com.entity.Log;
import com.entity.User;
@Component
public class UserServiceImpl {

    private UserDao userDao;
    private LogDao logDao;
    
    @Transactional
    public void add(User user) {
        userDao.save(user);
        Log log = new Log();
        log.setContent(user.getName());
        logDao.save(log);
    }
    
    public void update(User user) {
        userDao.update(user);
    }
    public void init() {// 初始方法
        System.out.println("init");
    }
    public void destroy() {// 销毁方法
        System.out.println("destory");
    }
    public UserDao getUserDao() {
        return userDao;
    }
    
    @Resource(name="userDaoImpl2")
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public LogDao getLogDao() {
        return logDao;
    }
    @Resource
    public void setLogDao(LogDao logDao) {
        this.logDao = logDao;
    }
}

UserDaoImpl2

package com.daoImpl;

import javax.annotation.Resource;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.dao.UserDao;
import com.entity.User;
@Component
public class UserDaoImpl2 implements UserDao{
    SessionFactory mySessionFactory;
    
    public void save(User user) {
        System.out.println(user.getName()+"-->"+user.getRemark()+"  save --调用UserDaoImpl2!");
        Session s = mySessionFactory.getCurrentSession();
        s.save(user);
    }
    
    public void update(User user) {
        System.out.println(user.getName()+"-->"+user.getRemark()+"  update  --调用UserDaoImpl2!");
        Session s = mySessionFactory.getCurrentSession();
        s.update(user);
    }
    
   
    public SessionFactory getMySessionFactory() {
        return mySessionFactory;
    }
    
     @Resource
    public void setMySessionFactory(SessionFactory mySessionFactory) {
        this.mySessionFactory = mySessionFactory;
    }
    
}

logImpl

package com.daoImpl;

import javax.annotation.Resource;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Component;

import com.dao.LogDao;
import com.entity.Log;
@Component
public class LogDaoImpl implements LogDao{
    SessionFactory mySessionFactory;
    
    public void save(Log log) {
        Session s = mySessionFactory.getCurrentSession();
        s.save(log);
    }
    public SessionFactory getMySessionFactory() {
        return mySessionFactory;
    }
    
    @Resource
    public void setMySessionFactory(SessionFactory mySessionFactory) {
        this.mySessionFactory = mySessionFactory;
    }
    

}

logDao,userDao

package com.dao;

import com.entity.Log;
import com.entity.User;

public interface LogDao {
    public void save(Log log);
}
package com.dao;

import com.entity.User;

public interface UserDao {
    public void save(User user);
    public void update(User user);
}

实体类

package com.entity;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class User {
    @Id
    private int id;
    private String name;
    private String remark;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getRemark() {
        return remark;
    }
    public void setRemark(String remark) {
        this.remark = remark;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
}
package com.entity;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Log {
    @Id
    private int id;
    private String content;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
}

最后是测试类

package com.serviceImpl.test;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.entity.User;
import com.serviceImpl.UserServiceImpl;

public class UserServiceImplTest {
    User user;

    @Before
    public void setUp() throws Exception {
        user = new User();
        user.setName("ttN");
        user.setRemark("ttR");
    }

    @Test
    public void testAdd() {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("beans.xml");
         UserServiceImpl UserServiceImpl = (UserServiceImpl)app.getBean("userServiceImpl");
         UserServiceImpl.add(user);//调用方法
    }
}

执行结果

ttN-->ttR save --调用UserDaoImpl2!
Hibernate: insert into User (name, remark, id) values (?, ?, ?)
Hibernate: insert into Log (content, id) values (?, ?)

接下来测试一下,如果写入日志失败是否能够回滚

模拟 模拟日志的ID重复了,导致失败

    @Transactional
    public void add(User user) {
        userDao.save(user);
        Log log = new Log();
        log.setId(1);
        logDao.save(log);
    }

测试类

@Before
    public void setUp() throws Exception {
        user = new User();
        user.setName("testRollBack");
        user.setRemark("testRollBack");
    }

    @Test
    public void testAdd() {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("beans.xml");
         UserServiceImpl UserServiceImpl = (UserServiceImpl)app.getBean("userServiceImpl");
         UserServiceImpl.add(user);//调用方法
    }

执行结果

testRollBack-->testRollBack save --调用UserDaoImpl2!
Hibernate: insert into User (name, remark, id) values (?, ?, ?)
Hibernate: insert into Log (content, id) values (?, ?)

报错信息

org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; 
Caused by: java.sql.SQLException: Column 'content' cannot be null

存入的USER数据已经回滚

实体类其实还可以通过自动扫描的方式获取

<!--  <property name="annotatedClasses">-->
      <property name="packagesToScan">  
            <list>
                    <value>com.entity</value>
<!-- 这些都不需要一个一个写了  <value>com.entity.User</value>--> 
<!--                        <value>com.entity.Log</value>-->
            </list>
        </property>
原文地址:https://www.cnblogs.com/sunfan1988/p/3495579.html