博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Atomikos+jdbcdslog——分布式事务管理输出实际log日志
阅读量:4047 次
发布时间:2019-05-25

本文共 7086 字,大约阅读时间需要 23 分钟。

前言

    想看实际产生的SQL,在一个数据源的情况下,最简单的方式是使用Log4jdbc。

    但在中,我们通过Atomikos实现了分布式事务,配置的是支持XA的DataSource,Log4jdbc这种在Driver上做文章的方法肯定不行。

    这里使用jdbcdslog的衍生项目jdbcdslog-exp来实现这个目标。jdbcdslog-exp比jdbcdslog更进了一步,输出的SQL,可以直接拷贝到PL/SQL等工具下执行。

 

依赖

jdbcdslog的依赖如下

com.googlecode.usc
jdbcdslog
1.0.6.2

 

配置方式

properties配置信息

这里以Oracle为例,properties内容如下,当然dataSource配置信息等需要两份

 

dev.jdbc.dataSource=org.jdbcdslog.ConnectionPoolXADataSourceProxydev.jdbc.url=jdbc:oracle:thin:@192.168.3.129:1521:gtf?targetDS=oracle.jdbc.xa.client.OracleXADataSourcedev.jdbc.username=adp_devdev.jdbc.password=adp_dev

 其中url相当于url + targetDS ,targetDS的值为普通方式下的dataSource。

 

配置文件

一个数据源的配置方式如下,另一个同理。其它配置参照

 

${dev.jdbc.url}
${dev.jdbc.username}
${dev.jdbc.password}

 

 

问题

实际运行时会发生错误,原因是由于AtomikosDataSourceBean中doInit方法中在该方法的最后才调用的PropertyUtils.setProperties(xaDataSource, xaProperties );这段代码,导致上面调用setLogWriter的时候缺少参数。

 

解决方法

1.提供一个无视set/get方法的反射工具;

2.AtomikosDataSourceBean中用到的参数AtomikosXAConnectionFactory 没有访问修饰符,无法访问的问题;

 3.重新实现一个AtomikosDataSourceBean类,并重写doInit方法。

 

(1)set/get方法的反射工具

 

import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;import org.apache.commons.lang3.StringUtils;import org.apache.commons.lang3.Validate;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.util.Assert;/** * 反射工具类. *  * 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数. *  * @author calvin */public class Reflections {	private static Logger logger = LoggerFactory.getLogger(Reflections.class);    /**     * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.     */    public static Object getFieldValue(final Object obj, final String fieldName) {        Field field = getAccessibleField(obj, fieldName);        if (field == null) {            throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");        }        Object result = null;        try {            result = field.get(obj);        } catch (IllegalAccessException e) {            logger.error("不可能抛出的异常{}", e.getMessage());        }        return result;    }    /**     * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.     *     * 如向上转型到Object仍无法找到, 返回null.     */    public static Field getAccessibleField(final Object obj, final String fieldName) {        Validate.notNull(obj, "object can't be null");        Validate.notBlank(fieldName, "fieldName can't be blank");        for (Class
superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) { try { Field field = superClass.getDeclaredField(fieldName); makeAccessible(field); return field; } catch (NoSuchFieldException e) {//NOSONAR // Field不在当前类定义,继续向上转型 } } return null; } /** * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 */ public static void makeAccessible(Field field) { if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier .isFinal(field.getModifiers())) && !field.isAccessible()) { field.setAccessible(true); } }}

 

(2)MyAtomikosXAConnectionFactory

解决自定义的AtomikosDataSourceBean无法访问问题,创建一个MyAtomikosXAConnectionFactory类,代码同AtomikosXAConnectionFactory完全一致;

 

 

(3)MyAtomikosDataSourceBean的doInit()方法

 

protected com.atomikos.datasource.pool.ConnectionFactory doInit() throws Exception {        if (xaDataSource == null) {            if (xaDataSourceClassName == null)                throwAtomikosSQLException("Property 'xaDataSourceClassName' cannot be null");            if (xaProperties == null)                throwAtomikosSQLException("Property 'xaProperties' cannot be null");        }        if (LOGGER.isInfoEnabled())            LOGGER.logInfo(this + ": initializing with [" + " xaDataSourceClassName=" + xaDataSourceClassName                    + "," + " uniqueResourceName=" + getUniqueResourceName() + "," + " maxPoolSize="                    + getMaxPoolSize() + "," + " minPoolSize=" + getMinPoolSize() + ","                    + " borrowConnectionTimeout=" + getBorrowConnectionTimeout() + "," + " maxIdleTime="                    + getMaxIdleTime() + "," + " reapTimeout=" + getReapTimeout() + ","                    + " maintenanceInterval=" + getMaintenanceInterval() + "," + " testQuery="                    + getTestQuery() + "," + " xaProperties=" + printXaProperties() + "," + " loginTimeout="                    + getLoginTimeout() + "," + " maxLifetime=" + getMaxLifetime() + "]");        if (xaDataSource == null) {            Class xadsClass = null;            try {                xadsClass = ClassLoadingHelper.loadClass(getXaDataSourceClassName());            } catch (ClassNotFoundException nf) {                AtomikosSQLException                        .throwAtomikosSQLException(                                "The class '"                                        + getXaDataSourceClassName()                                        + "' specified by property 'xaDataSourceClassName' could not be found in the classpath. Please make sure the spelling is correct, and that the required jar(s) are in the classpath.",                                nf);            }            Object driver = xadsClass.newInstance();            if (!(driver instanceof XADataSource)) {                AtomikosSQLException                        .throwAtomikosSQLException("The class '"                                + getXaDataSourceClassName()                                + "' specified by property 'xaDataSourceClassName' does not implement the required interface javax.jdbc.XADataSource. Please make sure the spelling is correct, and check your JDBC driver vendor's documentation.");            }            xaDataSource = (XADataSource) driver;            PropertyUtils.setProperties(xaDataSource, xaProperties);            ConnectionPoolXADataSourceProxy proxy = (ConnectionPoolXADataSourceProxy) xaDataSource;            XADataSource targetDs = (XADataSource) Reflections.getFieldValue(proxy, "targetDS");            targetDs.setLoginTimeout(getLoginTimeout());            // xaDataSource.setLoginTimeout ( getLoginTimeout() );            targetDs.setLogWriter(getLogWriter());        }        JdbcTransactionalResource tr = new JdbcTransactionalResource(getUniqueResourceName(), xaDataSource);        com.atomikos.datasource.pool.ConnectionFactory cf = new MyAtomikosXAConnectionFactory(xaDataSource,                tr, this);        Configuration.addResource(tr);        return cf;    }

 

(4)logback配置文件

 

 

看名就知道输出的是哪一部分数据,如果只看SQL,用org.jdbcdslog.StatementLogger就够了。

 

至此,Atomikos+jdbcdslog配置成功

转载地址:http://vmyci.baihongyu.com/

你可能感兴趣的文章
教育数字智能化能为现有体系带来新的起点
查看>>
媒体广告业如何将内容资产进行高效地综合管理与利用
查看>>
能源化工要怎么管控核心数据
查看>>
媒体广告业如何运用云盘提升效率
查看>>
企业如何运用企业云盘进行数字化转型-实现新发展
查看>>
司法如何运用电子智能化加快现代化建设
查看>>
iSecret 1.1 正在审核中
查看>>
IOS开发的开源库
查看>>
IOS开发的开源库
查看>>
Jenkins - sonarqube 代码审查
查看>>
Jenkins + Docker + SpringCloud 微服务持续集成(一)
查看>>
Jenkins + Docker + SpringCloud 微服务持续集成 - 单机部署(二)
查看>>
Jenkins + Docker + SpringCloud 微服务持续集成 - 高可用集群部署(三)
查看>>
Golang struct 指针引用用法(声明入门篇)
查看>>
Linux 粘滞位 suid sgid
查看>>
C#控件集DotNetBar安装及破解
查看>>
Winform皮肤控件IrisSkin4.dll使用
查看>>
Winform多线程
查看>>
C# 托管与非托管
查看>>
Node.js中的事件驱动编程详解
查看>>