- 浏览: 261905 次
- 性别:
- 来自: 多伦多
文章分类
- 全部博客 (127)
- Java 基础 (46)
- Java EE (3)
- Clouds (1)
- Spring 编程 (7)
- Spring Batch 编程 (1)
- Quartz 编程 (9)
- Seam 编程 (4)
- Hibernate 编程 (1)
- JSF 编程 (3)
- jQuery 编程 (3)
- Interview Question 汇总 (3)
- 日常应用 (3)
- Maven 编程 (2)
- WebService 编程 (10)
- Scala 编程 (5)
- Coherence 编程 (8)
- OO 编程 (1)
- Java 线程 (6)
- DB 编程 (2)
- WebService 安全 (4)
- Oracle Fusion 编程 (2)
- JavsScript/Ajax 编程 (1)
最新评论
-
chainal:
赞,说的很好
Scala 有趣的Trait -
wuliupo:
RRRR-MM-DD HH24:MI:SS
如何让Oracle SQL Developer显示的包含在日期字段中的时间 -
pengain:
...
使用Spring Roo ,感受ROR式的开发 -
zeng1990:
def getPersonInfo() = {
(&quo ...
Java 的继位人? - Scala简介 -
zeng1990:
我使用的是2.9.2版本的!
Java 的继位人? - Scala简介
这篇文章的想法来自于过去的两篇文章:《设计自己的MVC框架》《设计模式之事务处理》
链接:
http://www.javaresearch.org/article/59935.htm
http://www.javaresearch.org/article/59043.htm
代码下载同样在www.126.com的邮箱里,用户名 sharesources 密码 javafans
本文只是学习性质的文章,我一开始的想法就是修改《设计模式之事务处理》,提供Annotation来提供事务支持,支持到方法级别。通过引入一个 @Transaction标注,如果被此标注的方法将自动享受事务处理。目的是学习下Annotation和加深下对声明式事务处理的理解。
Annotation是JDK5引入的新特性,现在越来越多的框架采用此特性来代替烦琐的xml配置文件,比如hibernate,ejb3, spring等。对Annotation不了解,请阅读IBM网站上的文章,还有推荐javaeye的Annotation专栏:http: //www.iteye.com/subject/Annotation
代码的示例是一个简单的用户管理例子。
首先,环境是mysql+jdk5+myeclipse5+tomcat5,在mysql中建立一张表adminusers:
create table adminusers(id int(10) auto_increment not null primary key,
name varchar(10) not null,
password varchar(10) not null,
user_type varchar(10));
然后在tomcat下建立一个数据源,把代码中的strutslet.xml拷贝到tomcat安装目录下的 /conf/Catalina/localhost目录里,请自行修改文件中的数据库用户名和密码,以及数据库名称。另外,把mysql的 jdbc驱动拷贝到tomcat安装目录下的common/lib目录。这样数据源就建好了。在web.xml中引用:
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/test</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
我的例子只是在《设计模式之事务处理》的基础上改造的,在那篇文章里,我讲解了自己对声明式事务处理的理解,并利用动态代理实现了一个 TransactionWrapper(事务包装器),通过业务代理工厂提供两种版本的业务对象:经过事务包装的和未经过事务包装的。我们在默认情况下包装业务对象中的所有方法,但实际情况是,业务对象中的很多方法不用跟数据库打交道,它们根本不需要包装在一个事务上下文中,这就引出了,我们为什么不提供一种方式来配置哪些方法需要事务控制而哪些并不需要?甚至提供事务隔离级别的声明?很自然的想法就是提供一个配置文件,类似spring式的事务声明。既然JDK5已经引入Annotation,相比于配置文件的烦琐和容易出错,我们定义一个@Transaction的annotation来提供此功能。
看下Transaction.java的代码:
package com.strutslet.db;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.sql.Connection;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Transaction {
//事务隔离级别,默认为read_committed
public int level() default Connection.TRANSACTION_READ_COMMITTED ;
}
@Transaction 标注只有一个属性level,level表示事务的隔离级别,默认为Read_Committed(也是一般JDBC驱动的默认级别,JDBC驱动默认级别一般于数据库的隔离级别一致)。 @Target(ElementType.METHOD)表示此标注作用于方法级别, @Retention(RetentionPolicy.RUNTIME)表示在运行时,此标注的信息将被加载进JVM并可以通过Annotation的 API读取。我们在运行时读取Annotation的信息,根据隔离级别和被标注的方法名决定是否将业务对象的方法加进事务控制。我们只要稍微修改下 TransactionWrapper:
//TransactionWrapper.java
package com.strutslet.db;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import com.strutslet.exception.SystemException;
public class TransactionWrapper {
public static Object decorate(Object delegate) {
return Proxy.newProxyInstance(delegate.getClass().getClassLoader(),
delegate.getClass().getInterfaces(), new XAWrapperHandler(
delegate));
}
static final class XAWrapperHandler implements InvocationHandler {
private final Object delegate;
XAWrapperHandler(Object delegate) {
// Cache the wrapped delegate, so we can pass method invocations
// to it.
this.delegate = delegate;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
Connection con = ConnectionManager.getConnection();
//得到Transaction标注
Transaction transaction = method.getAnnotation(Transaction.class);
//如果不为空,说明代理对象调用的方法需要事务控制。
if (transaction != null) {
// System.out.println("transaction.." + con.toString());
// 得到事务隔离级别信息
int level = transaction.level();
try {
if (con.getAutoCommit())
con.setAutoCommit(false);
//设置事务隔离级别
con.setTransactionIsolation(level);
//调用原始对象的业务方法
result = method.invoke(delegate, args);
con.commit();
con.setAutoCommit(true);
} catch (SQLException se) {
// Rollback exception will be thrown by the invoke method
con.rollback();
con.setAutoCommit(true);
throw new SystemException(se);
} catch (Exception e) {
con.rollback();
con.setAutoCommit(true);
throw new SystemException(e);
}
} else {
result = method.invoke(delegate, args);
}
return result;
}
}
}
现在,看下我们的UserManager业务接口,请注意,我们是使用动态代理,只能代理接口,所以要把@Transaction标注是接口中的业务方法(与EJB3中的Remote,Local接口类似的道理):
package com.strutslet.demo.service;
import java.sql.SQLException;
import com.strutslet.db.Transaction;
import com.strutslet.demo.domain.AdminUser;
public interface UserManager {
//查询,不需要事务控制
public boolean checkUser(String name, String password) throws SQLException;
//新增一个用户,需要事务控制,默认级别
@Transaction
public boolean addUser(AdminUser user) throws SQLException;
}
要把addUser改成其他事务隔离级别(比如oracle的serializable级别),稍微修改下:@Transaction(level=Connection.TRANSACTION_SERIALIZABLE)
public boolean addUser(AdminUser user) throws SQLException;
不准备详细解释例子的业务流程,不过是登录和增加用户两个业务方法,看下就明白。阅读本文前最好已经读过开头提过的两篇文章。我相信代码是最好的解释:)
链接:
http://www.javaresearch.org/article/59935.htm
http://www.javaresearch.org/article/59043.htm
代码下载同样在www.126.com的邮箱里,用户名 sharesources 密码 javafans
本文只是学习性质的文章,我一开始的想法就是修改《设计模式之事务处理》,提供Annotation来提供事务支持,支持到方法级别。通过引入一个 @Transaction标注,如果被此标注的方法将自动享受事务处理。目的是学习下Annotation和加深下对声明式事务处理的理解。
Annotation是JDK5引入的新特性,现在越来越多的框架采用此特性来代替烦琐的xml配置文件,比如hibernate,ejb3, spring等。对Annotation不了解,请阅读IBM网站上的文章,还有推荐javaeye的Annotation专栏:http: //www.iteye.com/subject/Annotation
代码的示例是一个简单的用户管理例子。
首先,环境是mysql+jdk5+myeclipse5+tomcat5,在mysql中建立一张表adminusers:
create table adminusers(id int(10) auto_increment not null primary key,
name varchar(10) not null,
password varchar(10) not null,
user_type varchar(10));
然后在tomcat下建立一个数据源,把代码中的strutslet.xml拷贝到tomcat安装目录下的 /conf/Catalina/localhost目录里,请自行修改文件中的数据库用户名和密码,以及数据库名称。另外,把mysql的 jdbc驱动拷贝到tomcat安装目录下的common/lib目录。这样数据源就建好了。在web.xml中引用:
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/test</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
我的例子只是在《设计模式之事务处理》的基础上改造的,在那篇文章里,我讲解了自己对声明式事务处理的理解,并利用动态代理实现了一个 TransactionWrapper(事务包装器),通过业务代理工厂提供两种版本的业务对象:经过事务包装的和未经过事务包装的。我们在默认情况下包装业务对象中的所有方法,但实际情况是,业务对象中的很多方法不用跟数据库打交道,它们根本不需要包装在一个事务上下文中,这就引出了,我们为什么不提供一种方式来配置哪些方法需要事务控制而哪些并不需要?甚至提供事务隔离级别的声明?很自然的想法就是提供一个配置文件,类似spring式的事务声明。既然JDK5已经引入Annotation,相比于配置文件的烦琐和容易出错,我们定义一个@Transaction的annotation来提供此功能。
看下Transaction.java的代码:
package com.strutslet.db;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.sql.Connection;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Transaction {
//事务隔离级别,默认为read_committed
public int level() default Connection.TRANSACTION_READ_COMMITTED ;
}
@Transaction 标注只有一个属性level,level表示事务的隔离级别,默认为Read_Committed(也是一般JDBC驱动的默认级别,JDBC驱动默认级别一般于数据库的隔离级别一致)。 @Target(ElementType.METHOD)表示此标注作用于方法级别, @Retention(RetentionPolicy.RUNTIME)表示在运行时,此标注的信息将被加载进JVM并可以通过Annotation的 API读取。我们在运行时读取Annotation的信息,根据隔离级别和被标注的方法名决定是否将业务对象的方法加进事务控制。我们只要稍微修改下 TransactionWrapper:
//TransactionWrapper.java
package com.strutslet.db;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import com.strutslet.exception.SystemException;
public class TransactionWrapper {
public static Object decorate(Object delegate) {
return Proxy.newProxyInstance(delegate.getClass().getClassLoader(),
delegate.getClass().getInterfaces(), new XAWrapperHandler(
delegate));
}
static final class XAWrapperHandler implements InvocationHandler {
private final Object delegate;
XAWrapperHandler(Object delegate) {
// Cache the wrapped delegate, so we can pass method invocations
// to it.
this.delegate = delegate;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
Connection con = ConnectionManager.getConnection();
//得到Transaction标注
Transaction transaction = method.getAnnotation(Transaction.class);
//如果不为空,说明代理对象调用的方法需要事务控制。
if (transaction != null) {
// System.out.println("transaction.." + con.toString());
// 得到事务隔离级别信息
int level = transaction.level();
try {
if (con.getAutoCommit())
con.setAutoCommit(false);
//设置事务隔离级别
con.setTransactionIsolation(level);
//调用原始对象的业务方法
result = method.invoke(delegate, args);
con.commit();
con.setAutoCommit(true);
} catch (SQLException se) {
// Rollback exception will be thrown by the invoke method
con.rollback();
con.setAutoCommit(true);
throw new SystemException(se);
} catch (Exception e) {
con.rollback();
con.setAutoCommit(true);
throw new SystemException(e);
}
} else {
result = method.invoke(delegate, args);
}
return result;
}
}
}
现在,看下我们的UserManager业务接口,请注意,我们是使用动态代理,只能代理接口,所以要把@Transaction标注是接口中的业务方法(与EJB3中的Remote,Local接口类似的道理):
package com.strutslet.demo.service;
import java.sql.SQLException;
import com.strutslet.db.Transaction;
import com.strutslet.demo.domain.AdminUser;
public interface UserManager {
//查询,不需要事务控制
public boolean checkUser(String name, String password) throws SQLException;
//新增一个用户,需要事务控制,默认级别
@Transaction
public boolean addUser(AdminUser user) throws SQLException;
}
要把addUser改成其他事务隔离级别(比如oracle的serializable级别),稍微修改下:@Transaction(level=Connection.TRANSACTION_SERIALIZABLE)
public boolean addUser(AdminUser user) throws SQLException;
不准备详细解释例子的业务流程,不过是登录和增加用户两个业务方法,看下就明白。阅读本文前最好已经读过开头提过的两篇文章。我相信代码是最好的解释:)
发表评论
-
设计模式之事务处理
2010-11-25 07:36 912转自 http://www.blogjava.net/kill ... -
设计自己的MVC框架(1)
2010-11-25 07:27 1251转自 http://www.blogjava.net/ ... -
设计自己的MVC框架(2)
2010-11-25 07:24 1178转自 http://www.blogjava.ne ... -
Jakarta Commons StringUtils类使用
2010-11-25 06:58 935转自http://www.blogjava.net/ ... -
Jakarta Commons ArrayUtils类使用
2010-11-25 06:57 1132转自http://www.blogjava.net/ ... -
Reflection的三个动态性质
2010-11-25 06:56 1013转自http://www.blogjava. ... -
用commons.fileupload实现文件的上传和下载
2010-11-25 06:55 1399转自http://www.blogjav ... -
JAVA基础:共享内存在Java中的实现和应用
2010-11-25 06:54 873(转自 http://www.bu ... -
JAVA变量类型之间的相互转换
2010-11-25 06:52 899(转自 http://www.builder.c ... -
优秀Java程序员必须了解的GC工作原理
2010-11-25 06:52 887(转自 http://www.build ... -
几种版权信息详解
2010-11-25 06:49 1131BSD开源协议(original ... -
Java JDK 1.4 JCE Provider issue.
2010-11-25 06:48 1174Bundled JCE provider in jdk1 ... -
Why use Map.entrySet() instead of Map.keySet()?
2010-11-25 06:45 1393(From http://www.coderan ... -
Credit Card Mod10 校验
2010-11-25 06:27 2076以下是几种Mod10的实现。第一种最为简洁,最后一种 ... -
如何知道方法的调用者
2010-11-25 05:57 7399转自http://hellboys.bok ... -
Java加解密的基础
2010-11-25 05:49 2821在Java的安全包中,包括了三部分内容: ... -
Java日志框架:SLF4J, Apache Common-Logging, Log4J和Logback
2010-11-25 05:47 1858Log4j Apache的一个开放源代码项目,通过 ... -
Java SE 6新特性:Instrumentation
2010-11-25 05:35 1076(转自http://baike.baidu.com ... -
JBOSS 启动 加载 过程
2010-09-11 00:26 3024(转自: http://blog.csdn.net/ylli_ ... -
JAVA性能优化—Sun Hotspot JDK JVM参数设置
2010-09-11 00:18 1206(转自: http://www.hashei.me/2009/ ...
相关推荐
Berkeley DB Java 版直接持久层基础1是指使用 Berkeley DB Java 版本来实现直接持久层的技术基础。直接持久层是一种数据访问技术,允许Java应用程序直接访问数据库,而不需要通过SQL来访问数据库。Berkeley DB Java ...
Hibernate Annotation中文教程 Hibernate 是 Java 数据库持久性的事实标准之一,它...Hibernate Annotation 库提供了一种强大及灵活的方法来声明持久性映射,简化了Hibernate 代码,使持久层的编码过程变得更为轻松。
本文将深入探讨Hibernate Annotation API的核心概念、使用方法及其优势。 1. **什么是Hibernate Annotation API** Hibernate Annotation API是Hibernate ORM的一种扩展,允许开发者使用Java注解(Annotations)来...
SpringBoot整合Spring Data JPA是现代Java开发中的常见实践,它极大地简化了数据库操作,让开发者可以更加专注于业务逻辑而不是繁琐的数据访问层实现。本文将详细介绍如何使用Spring Boot搭建一个基于Spring Data ...
使用 Hibernate 注解可以简化 Hibernate 代码,使持久层的编码过程变得更为轻松。 传统上,Hibernate 的配置依赖于外部 XML 文件:数据库映射被定义为一组 XML 映射文件,并且在启动时进行加载。在最近发布的几个 ...
在Java Web开发中,S2SH(Struts2 + Spring + Hibernate)是一个常见的技术栈,它结合了MVC框架Struts2、依赖注入容器Spring以及持久层框架Hibernate,以实现高效且灵活的Web应用开发。在这个基于Annotation并对DAO...
在Java世界中,Hibernate是一个流行的持久层框架,它极大地简化了数据库操作,尤其是在对象关系映射(ORM)方面。在这个项目中,我们将深入探讨Hibernate如何通过注解来简化数据库操作。 首先,让我们了解什么是...
### Hibernate Annotation 中文文档知识点概览 #### 一、创建注解项目 ##### 1.1 系统需求 在创建一个使用 Hibernate 注解的项目之前,需要满足一定的系统环境需求,例如支持 Java 的开发环境、JDK 版本、支持 ...
Hibernate是一个流行的Java持久化框架,它使得开发人员可以更加便捷地在对象关系映射(ORM)层工作。在Hibernate中,注解(Annotation)是一种声明式的方法,用于配置实体类、属性以及它们与数据库表之间的映射关系...
3. **Hibernate框架**:Hibernate是一个持久层框架,提供了对象关系映射(ORM)功能,使得我们可以用面向对象的方式来操作数据库。在使用注解的Hibernate中,我们不再需要XML配置文件来描述实体类和表之间的映射关系...
本文将深入探讨如何结合使用Hibernate和Spring框架来构建高效、稳定的事务持久层。Hibernate作为一款流行的对象关系映射(ORM)工具,能够有效地简化Java应用与关系型数据库之间的交互;而Spring框架则以其强大的...
MyBatis是一个轻量级的持久层框架,它简化了SQL操作,将SQL语句与Java代码解耦。通过XML或注解配置,MyBatis可以将SQL与Java对象映射起来,实现了数据库查询和结果集的自动映射。这使得开发者能够更加专注于SQL的...
接着,MyBatis是一个轻量级的持久层框架,它允许开发者用SQL语句直接操作数据库,同时结合了动态SQL的功能。在注解方式下,MyBatis的Mapper接口可以与XML配置文件分离,通过`@Select`、`@Insert`、`@Update`、`@...
本教程将深入探讨如何结合这两个强大的工具来构建事务持久层,实现高效、灵活的数据访问。 首先,Spring是一个开源的应用框架,它提供了一整套服务,包括依赖注入(DI)、面向切面编程(AOP)、事务管理等,极大地...
在IT行业中,MyBatis作为一个轻量级的持久层框架,深受广大开发者的喜爱。它提供了灵活的SQL映射机制,使得Java对象和数据库表之间的映射变得简单易行。本篇文章将聚焦于MyBatis中的注解(Annotation)与XML配置的...
而MyBatis则是一个轻量级的持久层框架,它将SQL与Java代码分离,使数据库操作更加灵活。本项目结合了两者,利用注解方式来实现数据库的增删查改操作,通过Maven进行项目管理和构建。 首先,我们来看Spring的注解...
总结来说,这个 "Spring Hibernate Annotation demo" 展示了如何在 Spring 框架中使用注解配置来管理依赖,以及如何利用 Hibernate 的注解进行数据持久化。同时,它还涉及到了 Flex 前端与后端的交互。通过学习这个 ...
《Hibernate-Annotation-3.4.0帮助文档》是一份详尽的指南,旨在帮助开发者理解和使用Hibernate ORM框架中的注解功能。Hibernate是Java领域中广泛使用的对象关系映射(ORM)工具,它极大地简化了数据库操作。在3.4.0...
在IT行业中,数据库操作是必不可少的一部分,特别是在Java开发领域,MyBatis作为一款优秀的持久层框架,被广泛应用。本文将详细讲解如何使用MyBatis的注解方式在MySQL和Oracle数据库上实现批量处理,旨在提高数据...
4. 注意性能:过度使用注解可能导致JVM内存压力增大,合理设计实体关系,优化查询,以提高性能。 综上,Hibernate注解为Java开发人员提供了更便捷、更直观的ORM解决方案。通过熟练掌握并合理运用这些注解,开发者...