快捷搜索:  as  2018  FtCWSyGV  С˵  test  xxx  Ψһ  w3viyKQx

澳门新葡亰平台9411小游戏_龟发之家论坛



这篇文章的设法主见来自于以前的两篇文章:《设计自己的MVC框架》《设计模式之事务处置惩罚》

链接:

http://java.chinaitlab.com/model/532056.html

http://java.澳门新葡亰平台9411小游戏chinaitlab.com/model/533095.html

代码下载同样在www.126.com的澳门新葡亰平台9411小游戏邮箱里,用户名 sharesources 密码 javafans

本文只是进修惯质的文章,我一开始的设法主见便是改动《设计模式之事务处置惩罚》,供给Annotation来供给事务支持,支持到措施级别。经由过程引入一个 @Transaction标注,假如被此标注的措施将自动享受事务处置惩罚。目的是进修下Annotation和加深下对声明式事务处置惩罚的理解。

Annotation是JDK5引入的新特点,现在越来越多的框架采纳此特点来代替啰嗦的xml设置设置设备摆设摆设文件,比如hibernate,ejb3, spring等。对Annotation不懂得,请涉猎IBM网站上的文章,还有保举javaeye的Annotation专栏:http: //www.javaeye.com/subject/Annotation

代码的示例是一个简单的用户治理例子。

首先,情况是mysql+jdk5+myeclipse5+tomcat5,在mysql中建立一张表adminusers:

create table adminusers(id int(10) auto_increment not null p澳门新葡亰平台9411小游戏rimary 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中引用:

DB Connection

jdbctest

javax.sql.DataSource

Container

我的例子只是在《设计模式之事务处置惩罚》的根基上改造的,在那篇文章里,我解说了自己对声明式事务处置惩罚的理解,并使用动态代理实现了一个 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.RetentionPo澳门新葡亰平台9411小游戏licy;

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.Invoca澳门新葡亰平台9411小游戏tionHandler;

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;

不准备具体解释例子的营业流程,不过是登录和增添用户两个营业措施,看下就明白。涉猎本文前最好已经读过开首提过的两篇文章。我信托代码是最好的解释:)

您可能还会对下面的文章感兴趣: