目录

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();
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>

最新文章

  1. 黄聪:如何为IIS增加svg和woff等字体格式的MIME
  2. C++实现VPN工具之代码示例
  3. RDBMS vs. NoSQL 合作还是竞争
  4. ES questions
  5. VB 核心编程及通用模块开发 笔记1
  6. [Redux] Avoiding Object Mutations with Object.assign() and ...spread
  7. java反射 -Class类
  8. 【Xamarin 在Mac OS 上的部署安装环境】
  9. Makefile的几个赋值运算符(转:笔记)
  10. [Python]从豆瓣电影批量获取看过这部电影的用户列表
  11. 关于Office 中的墨迹功能(可作word电子签名)
  12. Python将列表中的string元素进行类型转换
  13. java中new关键字和newInstance()方法的区别
  14. JavaScript(三)
  15. vue项目总结
  16. 使用idea对spring boot项目打jar和war包[文件]
  17. Ajax请求的几个小练习
  18. oracle中delete、truncate、drop的区别
  19. centos 6.8 启动损坏修复实验
  20. HashMap原理&lt;转&gt;

热门文章

  1. JS中的Global对象
  2. 如果CDN服务器出了问题,怎么做不影响自己的网站
  3. hbase查询基于标准sql规范中间件Phoenix
  4. Tarjan在图论中的应用(一)——用Tarjan来实现强连通分量缩点
  5. Centos 编译安装bind错误
  6. pandas 代码
  7. 输入hostname -f提示:hostname: Unknown host
  8. Incorrect key file for table &#39;./xx_db/xx_table.MYI&#39;; try to repair it
  9. Bootstrap历练实例:简单的可折叠
  10. Dart Socket 与Java Socket连接