- 浏览: 74575 次
- 性别:
- 来自: 大连
最新评论
-
Heart.X.Raid:
//非递归后序遍历二叉树
void aftorder_t ...
树的遍历 -
zhangjunji111:
airlink 写道建议你再加个0来循环。
我的测试结果是10 ...
Spring的获取Bean的性能测试。 -
airlink:
建议你再加个0来循环。我的测试结果是10倍以上的差距。spri ...
Spring的获取Bean的性能测试。 -
rmn190:
结果中哪一个是C++的,哪一个Java的呢? 楼主最好用一个t ...
简单的c++排序跟java的性能比较。仅仅学习。 -
moshalanye:
每个对象都有一个隐含锁静态对象属于Class对象,非晶态对象属 ...
Java里面的同步跟oracle的锁的联想
事务管理:
分global事务管理和local事务管理,global要跨越多个事务资源,而local一般是本地资源,如JDBC,比较好控制。
下面的例子展示怎么Spring的事务管理。声明式事务管理
其实个人感觉还是手工控制事务舒服一些,因为被Spring管理后,觉得真的很简单了,特感觉没有深度东西可以做了。。。个人感受。
此代码是ProSpring书上面,经过简单改造,用Mysql数据库,把不完整的代码补充完整。
数据库:
DROP TABLE IF EXISTS `accounts`;
CREATE TABLE `accounts` (
`AccountId` int(10) unsigned NOT NULL auto_increment,
`AccountNumber` varchar(20) NOT NULL,
`Balance` decimal(10,2) NOT NULL,
PRIMARY KEY (`AccountId`),
UNIQUE KEY `AccountId` (`AccountNumber`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312;
DROP TABLE IF EXISTS `history`;
CREATE TABLE `history` (
`HistoryId` bigint(20) unsigned NOT NULL auto_increment,
`Account` varchar(20) NOT NULL,
`Operation` varchar(50) NOT NULL,
`Amount` decimal(10,2) NOT NULL,
`TransactionDate` timestamp NOT NULL,
`TargetAccount` varchar(20) default NULL,
UNIQUE KEY `HistoryId` (`HistoryId`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312;
--
-- Dumping data for table `history`
--
接口操作方法:
package com.apress.prospring.ch12.business;
import java.math.BigDecimal;
import com.apress.prospring.ch12.domain.Account;
public interface AccountManager {
/**
* 插入账户
* @param account
*/
public void insert(Account account);
/**
* 往账户里面存钱
* @param accountId
* @param amount
*/
public void deposit(String accountId, BigDecimal amount);
/**
* 从sourceAccount往targetAccount转账
* @param sourceAccount
* @param targetAccount
* @param amount
*/
public void transfer(String sourceAccount, String targetAccount, BigDecimal amount);
/**
* 数据库中账户的数量
* @return
*/
public int count();
}
抽象类实现:
package com.apress.prospring.ch12.business;
import java.math.BigDecimal;
import java.util.Date;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.InitializingBean;
import com.apress.prospring.ch12.domain.Account;
import com.apress.prospring.ch12.domain.AccountDao;
import com.apress.prospring.ch12.domain.History;
import com.apress.prospring.ch12.domain.HistoryDao;
public abstract class AbstractAccountManager
implements InitializingBean, AccountManager {
private AccountDao accountDao;
private HistoryDao historyDao;
protected void doInsert(Account account) {
getAccountDao().insert(account);
History history = new History();
history.setAccount(account.getAccountNumber());
history.setAmount(account.getBalance());
history.setOperation("Initial deposit");
history.setTargetAccount(null);
history.setTransactionDate(new Date());
getHistoryDao().insert(history);
}
protected void doDeposit(String accountId, BigDecimal amount) {
History history = new History();
history.setAccount(accountId);
history.setAmount(amount);
history.setOperation("Deposit");
history.setTargetAccount(null);
history.setTransactionDate(new Date());
getAccountDao().updateBalance(accountId, amount);
getHistoryDao().insert(history);
}
protected void doTransfer(String sourceAccount,
String targetAccount, BigDecimal amount) {
Account source = getAccountDao().getAccountById(sourceAccount);
if (source.getBalance().compareTo(amount) > 0) {
// transfer allowed
getAccountDao().updateBalance(sourceAccount, amount.negate());
getAccountDao().updateBalance(targetAccount, amount);
History history = new History();
history.setAccount(sourceAccount);
history.setAmount(amount);
history.setOperation("Paid out");
history.setTargetAccount(targetAccount);
history.setTransactionDate(new Date());
getHistoryDao().insert(history);
history = new History();
history.setAccount(targetAccount);
history.setAmount(amount);
history.setOperation("Paid in");
history.setTargetAccount(sourceAccount);
history.setTransactionDate(new Date());
getHistoryDao().insert(history);
} else {
throw new RuntimeException("Not enough money");
}
}
protected int doCount() {
return getAccountDao().getCount();
}
public final void afterPropertiesSet() throws Exception {
if (accountDao == null) throw new
BeanCreationException("Must set accountDao");
if (historyDao == null) throw new
BeanCreationException("Must set historyDao");
initManager();
}
protected void initManager() {
}
protected AccountDao getAccountDao() {
return accountDao;
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
protected HistoryDao getHistoryDao() {
return historyDao;
}
public void setHistoryDao(HistoryDao historyDao) {
this.historyDao = historyDao;
}
}
默认实现:
package com.apress.prospring.ch12.business;
import java.math.BigDecimal;
import com.apress.prospring.ch12.domain.Account;
public class DefaultAccountManager extends AbstractAccountManager {
public void insert(Account account) {
doInsert(account);
}
public void deposit(String accountId, BigDecimal amount) {
doDeposit(accountId, amount);
}
public void transfer(String sourceAccount, String targetAccount, BigDecimal amount) {
doTransfer(sourceAccount, targetAccount, amount);
}
public int count() {
return 0;
}
}
数据库操作的两个接口类dao
package com.apress.prospring.ch12.domain;
import java.math.BigDecimal;
public interface AccountDao {
/**
* get account by account number
* @param accountId
* @return
*/
public Account getAccountById(String accountId);
/**
* @param sourceAccount
* @param amount
*/
public void updateBalance(String sourceAccount, BigDecimal amount);
/**
* @param account
*/
public void insert(Account account);
/**
* @return
*/
public int getCount();
}
package com.apress.prospring.ch12.domain;
// in HistoryDao.java:
import java.util.List;
public interface HistoryDao {
public List getByAccount(int account);
public History getById(int historyId);
public void insert(History history);
}
AccountDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap>
<typeAlias type="com.apress.prospring.ch12.domain.Account" alias="account"/>
<resultMap class="account" id="result">
<result property="accountNumber" column="AccountNumber"/>
<result property="balance" column="Balance"/>
</resultMap>
<insert id="insertAccout" parameterClass="account">
insert into accounts (AccountNumber, Balance) values (#accountNumber#,#balance#)
</insert>
<select id="getAccountById" resultMap="result" parameterClass="int" >
select * from accounts where AccountNumber=#value#
</select>
<update id="update" parameterClass="map">
update accounts set Balance=#balance# where AccountNumber=#accountNumber#
</update>
</sqlMap>
HistoryDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap>
<typeAlias type="com.apress.prospring.ch12.domain.History" alias="history"/>
<resultMap class="history" id="result">
<result property="account" column="Account"/>
<result property="operation" column="Operation"/>
<result property="amount" column="Amount"/>
<result property="transactionDate" column="TransactionDate"/>
<result property="targetAccount" column="TargetAccount"/>
</resultMap>
<insert id="insertHistory" parameterClass="history">
insert into history (Account,Operation,Amount,TransactionDate, TargetAccount)
values (#account#,#operation#,#amount#,#transactionDate#,#targetAccount#)
</insert>
</sqlMap>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- Data source bean -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost/test</value></property>
<property name="username"><value>root</value></property>
<property name="password"><value>G@111111</value></property>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource"><ref local="dataSource"/></property>
</bean>
<bean id="sqlMapClient"
class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation"><value>sqlMapConfig.xml</value></property>
</bean>
<bean id="accountDao"
class="com.apress.prospring.ch12.data.SqlMapClientAccountDao">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="sqlMapClient"><ref local="sqlMapClient"/></property>
</bean>
<bean id="historyDao"
class="com.apress.prospring.ch12.data.UnreliableSqlMapClientHistoryDao">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="sqlMapClient"><ref local="sqlMapClient"/></property>
</bean>
<bean id="accountManagerTarget"
class="com.apress.prospring.ch12.business.DefaultAccountManager">
<property name="accountDao"><ref local="accountDao"/></property>
<property name="historyDao"><ref local="historyDao"/></property>
</bean>
<bean id="accountManager"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager"/></property>
<property name="target"><ref local="accountManagerTarget"/></property>
<property name="transactionAttributes">
<props>
<prop key="insert*">
PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
<prop key="transfer*">
PROPAGATION_REQUIRED, ISOLATION_SERIALIZABLE</prop>
<prop key="deposit*">
PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
</props>
</property>
</bean>
</beans>
package com.apress.prospring.ch12.business;
import java.math.BigDecimal;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.apress.prospring.ch12.domain.Account;
public class AccountManagerTest {
private ApplicationContext context;
private void run() {
System.out.println("Initializing application");
context = new ClassPathXmlApplicationContext(new String[] {
"applicationContext.xml" });
AccountManager manager = (AccountManager)context.getBean(
"accountManager");
int count = manager.count();
int failures = 0;
int attempts = 100;
for (int i = 0; i < attempts; i++) {
Account a = new Account();
a.setBalance(new BigDecimal(10));
a.setAccountNumber("123 " + i);
try {
manager.insert(a);
} catch (RuntimeException ex) {
System.out.println("Failed to insert account " + ex.getMessage());
failures++;
}
}
System.out.println("Attempts : " + attempts);
System.out.println("Failures : " + failures);
System.out.println("Prev count: " + count);
System.out.println("New count : " + manager.count());
System.out.println("Done");
}
public static void main(String[] args) {
new AccountManagerTest().run();
}
}
- spring_app.zip (5.3 MB)
- 下载次数: 413
发表评论
-
Java里面的同步跟oracle的锁的联想
2009-07-16 08:21 1172暂时不讨论。不明白 -
想做一个JMSServer,实现10000/s可以吗?
2009-07-02 17:51 1035本贴已经删除,有很多东西需要学习。谢谢大大家给予的建议和批评啊 ... -
Java String中的hashCode函数
2009-06-27 09:43 4264String 类中的hash函数如下: public ... -
java中HashCode的作用和Map的实现结构
2009-06-25 22:50 3906Map 是一种数据结构,用来实现key和value 的映射。通 ... -
使用Spring后会带来什么好处
2009-06-23 16:20 9331 为你的项目增加一个管家,你不必写很多的代码去实现一些框架已 ... -
jboss EJB
2009-06-15 14:39 817暂时不讨论。不明白 -
简单的归并排序算法例子
2009-06-14 21:36 1062import java.util.ArrayList;impo ... -
Jboss消息中间件跟IBM MQ的比较
2009-06-12 21:28 1602简单说几点. 1 jboss消息以java编写,嵌入到jbo ... -
Jboss message point to point
2009-06-12 21:17 884下面的例子程序是从Jbos ... -
Jboss SubscriberClient 主动式接受消息
2009-06-11 21:35 691下载jboss后面,按照默认启动就可以。 packag ... -
http报文
2009-06-11 21:09 2550HTTP报文是面向文本的,报文中的每一个字段都是一些ASCII ... -
面向对象的三个特征
2009-06-11 20:52 778面向对象的三个基本特征是:封装、继承、多态。 Th ... -
java的同样排序函数的执行效率
2009-06-11 20:50 1303package com.liuxt.sort; import ... -
apache ab 性能测试
2009-06-10 20:22 1489测试结果的说明:参考文章:http://www.phpchin ... -
java虚拟机规范 3.5 运行期数据区
2009-06-10 14:35 923http://java.sun.com/docs/books/ ... -
java SQL注入分析程序
2009-06-09 22:11 1965DROP TABLE IF EXISTS `user`;CRE ... -
java virtural machine data type
2009-06-08 16:35 673data ... -
parse xml file with dom and sax .
2009-06-07 13:47 908基于dom方式的dom4j和jdom以及JDK提供的dom方式 ... -
memcached 的linux配置
2009-06-03 22:45 681详细参选下面的连接: http://www.ccvita.co ... -
memcached 的java 客户端的简单测试代码
2009-06-03 22:42 1548import java.io.IOException; imp ...
相关推荐
在本文中,我们将深入探讨Spring框架中的事务管理。Spring是一个广泛应用的Java企业级应用开发框架,它提供...如果你想要深入了解,可以参考提供的博客链接或其他相关资料,进一步学习Spring事务管理的细节和最佳实践。
Spring事务管理分为编程式事务管理和声明式事务管理两种方式。编程式事务管理通过使用PlatformTransactionManager接口的begin、commit、rollback等方法直接控制事务的生命周期,这种方式灵活但容易导致代码过于繁琐...
本主题将深入探讨“Spring事务案例分析.zip”中的关键知识点,包括Spring事务管理及其在实际项目中的应用。 首先,我们来了解什么是Spring事务管理。在分布式系统或数据库操作中,事务管理是确保数据一致性和完整性...
本文将深入探讨在Spring框架中如何管理事务,以“Spring 事务简单完整例子”为出发点,结合标签“spring,事务,jdbc事务”,我们将详细解释Spring事务管理的原理和实践。 首先,Spring提供了两种事务管理方式:编程...
为了更好地理解Spring事务管理的实际应用,可以通过以下简单的例子进行演示: ```java @Service public class AccountService { @Autowired private AccountRepository accountRepository; @Transactional...
虽然提供的示例是入门级别的,但它揭示了Spring事务管理的核心概念,为进一步学习和理解Spring事务处理的高级特性奠定了基础。在实际项目中,我们需要根据需求选择合适的配置,确保事务的正确性和数据的一致性。
在Spring框架中,事务管理是核心功能之一,它确保了数据操作的一致性和完整性。本教程将深入探讨如何在Spring中实现自定义事务管理器...这将加深你对Spring事务管理的理解,帮助你在实际项目中更加熟练地运用这些技术。
总结来说,本例子通过`TransactionProxyFactoryBean`和`@Transactional`展示了如何在Spring中实现声明式事务管理,这两种方式都利用了AOP来封装事务逻辑,使代码更加整洁,降低了事务管理的复杂性。在实际应用中,...
在Spring框架中,事务管理是核心特性之一,用于确保数据操作的一致性和完整性。当一个方法(A方法)内部调用另一个方法(B方法)时,可能会遇到事务控制...这个示例代码对于理解和调试Spring事务管理的问题非常有帮助。
通过运行这些例子,你将对Spring事务管理有更深入的理解,知道何时选择编程式还是声明式事务,以及如何有效地处理事务异常。 总之,Spring的事务管理是其强大功能的一部分,无论是编程式还是声明式,都能帮助开发者...
Spring事务管理是Spring框架的核心特性之一,它提供了一种强大且灵活的方式来管理应用程序中的事务边界。在企业级Java应用中,事务处理是确保数据一致性、完整性和可靠性的关键部分。本篇文章将深入探讨Spring的事务...
Spring事务管理提供了一种声明式的方式来控制事务边界,使得开发者无需显式地调用开始、提交或回滚事务。 在Spring中,有以下两种事务管理方式: 1. **编程式事务管理**:开发者需要手动调用`...
Spring事务管理主要分为两种方式:编程式事务管理和声明式事务管理。编程式事务管理是通过编写代码来控制事务的开始、提交、回滚等操作,而声明式事务管理则是通过配置或注解来定义事务边界,更加直观和易于使用。 ...
Spring事务管理提供了统一的事务处理模型,使得开发者无需关注具体数据库访问技术的事务细节,简化了事务控制代码,提高了代码的可读性和可维护性。无论是使用注解还是AOP配置,都能有效地管理和协调事务,确保应用...
Spring事务管理还支持编程式事务管理,但这需要开发者手动调用`TransactionTemplate`或`PlatformTransactionManager`来控制事务的开始、提交、回滚等操作,相对而言更复杂,但在某些特定场景下更有灵活性。...
### Spring事务管理的方法 #### 一、引言 在企业级应用开发中,事务管理是一项至关重要的技术。Spring框架作为Java领域中一个非常流行的轻量级框架,为开发者提供了多种方式来实现事务管理,其中主要分为编程式...
总之,这个“spring简单实例 事务回滚”案例为我们提供了一个学习Spring事务管理的好起点。通过理解如何配置事务管理器,使用`@Transactional`注解,以及异常处理机制,我们可以更好地掌握Spring如何保证数据的一致...
Spring事务管理分为编程式和声明式两种。编程式事务管理通过编程的方式(如使用`TransactionTemplate`或直接调用`PlatformTransactionManager`)来控制事务的开始、提交、回滚等操作。而声明式事务管理则是在配置...
在整个源代码分析中,我们可以看到 Spring 实现声明式事务管理有三个部分: 1. 对在上下文中配置的属性的处理,这里涉及的类是 TransactionAttributeSourceAdvisor,这是一个通知器,用它来对属性值进行处理,属性...