- 浏览: 3008992 次
- 性别:
- 来自: 河南
文章分类
- 全部博客 (340)
- Java综合 (26)
- 程序人生 (53)
- RIA-ExtJS专栏 (18)
- RIA-mxGraph专栏 (4)
- RIA-Flex4专栏 (43)
- 框架-Spring专栏 (16)
- 框架-持久化专栏 (22)
- 框架-Struts2专栏 (11)
- 框架-Struts专栏 (12)
- SQL/NOSQL (12)
- 报表/图表 (2)
- 工作流 (5)
- XML专栏 (4)
- 日常报错解决方案 (5)
- Web前端-综合 (12)
- Web/JSP (14)
- Web前端-ajax专栏 (14)
- Web前端-JQuery专栏 (9)
- IDE技巧 (6)
- FILE/IO (14)
- 远程服务调用 (2)
- SSO单点登录 (2)
- 资源分享 (22)
- 云计算 (1)
- 项目管理 (3)
- php专栏 (1)
- Python专栏 (2)
- Linux (1)
- 缓存系统 (1)
- 队列服务器 (1)
- 网络编程 (0)
- Node.js (1)
最新评论
-
hui1989106a:
我的也不能解压,360和好压都试了,都不行
《Spring in Action》完整中文版分享下载 -
temotemo:
这些example有些过时了,官方建议使用HBase-1.0 ...
Java操作Hbase进行建表、删表以及对数据进行增删改查,条件查询 -
zy8102:
非常感谢~
HeadFirst系列之七:《深入浅出SQL》原版高清PDF电子书分享下载 -
zy8102:
重命名了一下搞定了
HeadFirst系列之七:《深入浅出SQL》原版高清PDF电子书分享下载 -
zy8102:
为什么下载以后老解压不了呢?
HeadFirst系列之七:《深入浅出SQL》原版高清PDF电子书分享下载
目前项目开发过程中对于Spring的事务管理,主要就这么两种方式:XML配置方式和注解方式
在平时开发中,Spring团队建议使用注解的方式进行配置,这样配置文件显得精简,同时也会做到精确控制。
注解方式
必须包
User.java
package com.javacrazyer.spring.bean;
public class User
{
private int id;
private String username;
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
}
这个user在mysql中肯定是要创建的
create table users
(
id int(11) not null auto_increment,
username varchar(20) not null,
primary key (id)
)
UserDAO.java类
package com.javacrazyer.spring.dao;
import java.util.List;
import com.javacrazyer.spring.bean.User;
public interface UserDAO
{
public void save(User user);
public void update(User user);
public User getUser(int id);
public void delete(int id);
public List<User> getAllUsers();
}
UserRowMapper类
package com.javacrazyer.spring.dao.impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import com.javacrazyer.spring.bean.User;
public class UserRowMapper implements RowMapper {
public Object mapRow(ResultSet rs, int index) throws SQLException {
User user = new User();
user.setUsername(rs.getString("username"));
user.setId(rs.getInt("id"));
return user;
}
}
UserDAOImpl.java具体实现类
package com.javacrazyer.spring.dao.impl;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.javacrazyer.spring.bean.User;
import com.javacrazyer.spring.dao.UserDAO;
@Transactional
public class UserDAOImpl implements UserDAO
{
//private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource)
{
//this.dataSource = dataSource;
this.jdbcTemplate=new JdbcTemplate(dataSource);
}
public void delete(int id)
{
jdbcTemplate.update("delete from users where id=?", new Object[]{id},
new int[]{java.sql.Types.INTEGER});
//jdbcTemplate.update("delete from users1 where id=10");
}
public List<User> getAllUsers()
{
return (List<User>)jdbcTemplate.query("select * from users", new UserRowMapper());
}
@Transactional(propagation=Propagation.NOT_SUPPORTED)
public User getUser(int id)
{
return (User)jdbcTemplate.queryForObject("select * from users where id=?", new Object[]{id},
new int[]{java.sql.Types.INTEGER}, new UserRowMapper());
}
public void save(User user)
{
jdbcTemplate.update("insert into users(username) values(?)", new Object[]{user.getUsername()},
new int[]{java.sql.Types.VARCHAR});
}
public void update(User user)
{
jdbcTemplate.update("update users set username=? where id=?", new Object[]{user.getUsername(),user.getId()},
new int[]{java.sql.Types.VARCHAR, java.sql.Types.INTEGER});
}
}
最后的测试类
package com.javacrazyer.spring.test;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.annotation.Transactional;
import com.javacrazyer.spring.bean.User;
import com.javacrazyer.spring.dao.UserDAO;
@Transactional
public class UserDAOImplTest
{
UserDAO userDAO;
@Before
public void init()
{
try {
ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
userDAO= (UserDAO) cxt.getBean("userDAO");
} catch (RuntimeException e) {
e.printStackTrace();
}
}
@Test
public void testDelete()
{
userDAO.delete(11);
}
@Test
public void testGetAllUsers()
{
for(User user : userDAO.getAllUsers()){
System.out.println(user.getUsername());
}
}
@Test
public void testGetUser()
{
User user = userDAO.getUser(1);
System.out.println(user.getUsername());
}
@Test
public void testSave()
{
for(int i=0; i<5; i++)
{
User user=new User();
user.setUsername("coolszy"+i);
userDAO.save(user);
}
}
@Test
public void testUpdate()
{
User user=userDAO.getUser(1);
user.setUsername("kuka");
userDAO.update(user);
}
}
Spring的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-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!--这里占位符配置可以配置在一个占位符类bean,也可以全局配置一句话就行 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- <bean id="propertyConfigurer"-->
<!-- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">-->
<!-- <property name="location" value="/WEB-INF/jdbc.properties" />-->
<!-- </bean>-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${driverClassName}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<!-- 连接池启动时的初始值 -->
<property name="initialSize" value="${initialSize}" />
<!-- 连接池的最大值 -->
<property name="maxActive" value="${maxActive}" />
<!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
<property name="maxIdle" value="${maxIdle}" />
<!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
<property name="minIdle" value="${minIdle}" />
</bean>
<!--spring事务管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 指定数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!--开启对注解的支持 -->
<tx:annotation-driven transaction-manager="txManager" />
<bean id="userDAO" class="com.szy.spring.dao.impl.UserDAOImpl">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
jdbc.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test
username=root
password=root
initialSize=1
maxActive=100
maxIdle=2
minIdle=1
在注解方式编写测试代码,代码运行正常。
在我们实现的每个方法中如delete()方法,如果delete方法是这样
public void delete(int id)
{
jdbcTemplate.update("delete from users where id=?", new Object[]{id},
new int[]{java.sql.Types.INTEGER});
jdbcTemplate.update("delete from users where id=?", new Object[]{id},
new int[]{java.sql.Types.INTEGER});
}
这样每条语句都会在各自的事务中执行,并不能保证在同一使用中执行,为了保证在同一事务中执行,我们应使用Spring容器提供的声明事务,我们在UserDAOImpl 类上加入@Transactional,表示该类受Spring事务管理。如果该类中每个方法不需要事务管理,如getUser方法,则在该方法前加入
@Transactional(propagation=Propagation.NOT_SUPPORTED)
XML配置方式
必须包
这里就UserDAOImpl.java,applicationContext.xml与上边不同
UserDAOImpl.java就是去掉了所有@Transactional的注解
applictionContext.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-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<!-- 连接池启动时的初始值 -->
<property name="initialSize" value="${initialSize}"/>
<!-- 连接池的最大值 -->
<property name="maxActive" value="${maxActive}"/>
<!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
<property name="maxIdle" value="${maxIdle}"/>
<!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
<property name="minIdle" value="${minIdle}"/>
</bean>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 指定数据源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
<aop:config>
<aop:pointcut id="transactionPointcut" expression="execution(* com.szy.spring.dao.impl..*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- 如果方法是以get开头,能不进行事务管理 -->
<tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<bean id="userDAO" class="com.szy.spring.dao.impl.UserDAOImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
这里没有了注解支持,而是配成了tx标签开头的声明式事务管理方式,基于aspectJ的配置
下面我们测试下数据库操作是否在同一事务中执行。
假设我们的delete方法如下:
public void delete(int id)
{
jdbcTemplate.update("delete from users where id=?", new Object[]{id},
new int[]{java.sql.Types.INTEGER});
jdbcTemplate.update("delete from users1 where id=10");
}
在第二条删除语句中,users1表是不存在的,如果两次update语句是在两个事务中执行,则第一条能成功执行,并且数据库中该id的记录已经被删除,而第二条由于不存在该表不能正常删除。如果在同一事务中执行,由于第二条update出错,数据库中不能删除任何记录。
测试代码
@Test
public void testDelete()
{
userDAO.delete(5);
}
程序报错,同时id=5的记录没有被删除。如果我们把配置文件中关于事务配置的信息给注释掉,再次测试,程序同样报错,但是id=5的记录被成功删除掉,这说明这两条update语句是在两个不同的事务中运行。
所以配置事务就是保证,无论方法中有多少条更新语句,那么我只要保证整个方法在同一个事务中执行就OK
发表评论
-
Spring温习(9)--配置hibernate信息
2010-11-04 09:45 3115有时候为了为了操作方便,我们时常在spring整合hibern ... -
Spring温习(8)--国际化的支持
2010-11-03 11:07 3786我今天介绍的国际化呢,平时基本上都用不上,我的项目中也从来没用 ... -
Spring温习(7)--有关定时任务Quartz的示例
2010-11-02 23:07 2826实际项目中有关定时任务的使用还是比较普遍的,比如定时做报表,定 ... -
Spring温习(6)--邮件发送实现
2010-10-28 21:55 7673Spring对邮件发送支持的很好,我们只要配置好邮件发送器,写 ... -
Spring温习(5)--CGLIB的动态代理[附AOP内部实现讲解]
2010-10-27 14:55 8882这篇文章紧接着上一篇静态代理和动态代理来说 前言: 到现在 ... -
Spring温习(4)--静态代理和动态代理
2010-10-27 11:27 3338代理模式分为静态代理和动态代理。静态代理就是我们自己定义的代理 ... -
Spring温习(3)--AutoWire自动装配
2010-10-27 09:48 3095在应用中,我们常常使用<ref>标签为JavaBe ... -
Spring温习(2)--IOC容器
2010-10-27 09:10 30481. Spring IoC的依赖注入 1) 使用构造方法来注入 ... -
Spring温习(1)--最基础的示例
2010-10-26 21:37 3493从现在开始,我将从Spring为起点,逐步复习几大框架各方面的 ... -
Spring数据源配置的三种方式
2010-10-26 15:25 3782spring数据源配置目前确切的说应该分为:spring容器自 ... -
Spring AOP的两种实现方式
2010-10-26 11:18 5835AOP常用实现方式是一个采用声明的方式来实现,一个采用注解的方 ... -
Spring AOP原理及拦截器
2010-10-26 10:38 147910原理 AOP(Aspect Oriented Pro ... -
在MyEclipse8.5中恢复jpetstore项目
2010-10-22 17:24 2321恢复jpetstore项目的过程1.在myeclipse8.5 ... -
SpringMVC关键问题讲解
2010-10-21 21:31 22923接着上篇文章,大家可能关心的那两个问题 1.control ... -
SpringMVC入门实例及详细讲解
2010-10-21 20:48 215123Spring 框架提供了构建 Web 应用程序的 ...
相关推荐
Spring 3.0 提供了两种事务管理配置方法:基于 XML 的事务管理和基于 @Transactional 的事务管理,这两种方法都是为了实现事务管理的目标,分别具有不同的配置方式和优缺点。 基于 XML 的事务管理 这种方法不需要...
本文将详细介绍Spring事务管理的四种方式:编程式事务管理、声明式事务管理、PlatformTransactionManager接口以及TransactionTemplate。 1. **编程式事务管理**:这是一种手动控制事务的方式,通过在代码中调用`...
首先,Spring提供了两种主要的事务管理方式:编程式事务管理和声明式事务管理。 1. **编程式事务管理**:通过使用`PlatformTransactionManager`接口及其实现类(如`JdbcTemplate`或`HibernateTemplate`),开发者...
本篇文章将详细探讨Spring中的三种事务管理方式:编程式事务管理、声明式事务管理和基于注解的事务管理。 首先,编程式事务管理是通过编码来控制事务的开始、提交、回滚等操作。Spring提供了...
每种事务管理方法都有其适用场景,选择哪种方式取决于项目需求、团队习惯以及对事务控制的精细程度。理解并灵活运用这五种事务管理方法,能有效提升Spring应用的稳定性和可维护性。在实际开发中,结合源码阅读和工具...
2. **Spring事务管理**:Spring提供了两种事务管理方式,即编程式事务管理和声明式事务管理。编程式事务管理通过TransactionTemplate或直接调用PlatformTransactionManager接口的方法来管理事务,而声明式事务管理则...
Spring事务原理是指Spring框架中的一种机制,用于管理事务,并提供了多种配置方式。事务是指一系列的操作,作为一个整体执行,如果其中某个操作失败,整个事务将回滚。Spring事务原理围绕着两个核心:...
Spring事务管理分为编程式事务管理和声明式事务管理两种方式。编程式事务管理通过使用PlatformTransactionManager接口的begin、commit、rollback等方法直接控制事务的生命周期,这种方式灵活但容易导致代码过于繁琐...
Spring 提供了两种事务管理方式:编程式事务管理和声明式事务管理。 1. 编程式事务管理:这是通过编写代码来控制事务的开始、提交和回滚。Spring 提供了PlatformTransactionManager接口,如...
Spring提供了声明式事务管理和编程式事务管理两种方式,其中声明式事务管理因其实现简单而被广泛应用。声明式事务主要通过Spring AOP(面向切面编程)来实现,它允许在方法执行前后添加事务逻辑而不改变原有代码逻辑。...
Spring事务管理主要包括两种类型:编程式事务管理和声明式事务管理。 - **编程式事务管理**:通过编写代码来控制事务的开始、提交或回滚等操作。这种方式灵活度高,但会使得代码变得冗余且难以维护。 - **声明式...
### Spring事务配置的五种方式详解 #### 一、引言 在企业级应用开发中,事务处理是非常重要的一部分,特别是在涉及多个数据库操作时。Spring框架提供了强大的事务管理功能,支持编程式和声明式两种事务处理方式。...
在Java应用中,Spring提供了两种主要的事务管理方式:编程式事务管理和声明式事务管理。 **编程式事务管理** 是通过调用`PlatformTransactionManager`接口提供的方法来手动控制事务的开始、提交、回滚。例如,你...
Spring的事务管理分为编程式事务管理和声明式事务管理两种方式。编程式事务管理需要开发者手动编写事务管理代码,虽然灵活但易出错,且侵入性强。声明式事务管理则是通过配置或注解来声明事务边界,更加简洁且易于...
在描述中提到的博客文章中,作者可能详细讲解了如何配置和使用这两种事务管理方式。通常,声明式事务管理是首选,因为它更简洁且易于维护。例如,可以使用@Transactional注解在方法级别声明一个事务,该方法内的所有...
在Spring中,事务管理分为编程式和声明式两种方式。本篇文章将详细解释Spring事务管理的流程,以及如何通过时序图来理解这一过程。 首先,我们来看Spring事务的流程。当一个事务开始时,通常会经历以下步骤: 1. *...
本教程将深入探讨 Spring 的编程式事务管理和声明式事务管理,帮助你理解这两种方式的差异与应用场景。 首先,编程式事务管理依赖于编程的方式显式地控制事务的开始、提交、回滚等操作。它通过实现 `...
Spring支持两种类型的事务管理:编程式事务管理和声明式事务管理。其中声明式事务管理因其易于使用和维护而被广泛采用。 ##### 1.1 Spring声明式事务介绍 Spring的声明式事务管理是通过配置文件或注解的方式来实现...
在Spring框架中,事务管理分为编程式事务管理和声明式事务管理两种方式。 一、编程式事务管理 编程式事务管理允许开发者在代码中显式地开始、提交、回滚事务。这种方式虽然灵活,但会使得业务代码变得复杂,不易...