• 瞅瞅Infinispan事务管理源码是啥样的


    希望可以更直观地了解Infinispan的事务管理,(提一点Infinispan是遵循LGPL,具体开源协议参阅《各种开源协议介绍 BSD、Apache Licence、GPL V2 、GPL V3 、LGPL、MIT》)本文重点在JTA的使用

    在上一篇《Ehcache 事务管理源码探析》中针对Ehcache的JTA事务管理说明了一番,是在JBoss服务器环境下使用JTA。同样在Infinispan中也具有获取JBoss容器事务管理器的能力,即配置事务查找器为 JBossTransactionManagerLookup,实现源码如下:

    /**
    * Uses JNDI to look-up the {
    @link TransactionManager} instance from "java:/TransactionManager".
    *
    *
    @author Bela Ban, Aug 26 2003
    *
    @since 4.0
    */
    public class JBossTransactionManagerLookup implements TransactionManagerLookup {

    public TransactionManager getTransactionManager() throws Exception {
    String as7Location = "java:jboss/TransactionManager";

    InitialContext initialContext = new InitialContext();
    try {
    // Check for JBoss AS 7
    return (TransactionManager) initialContext.lookup(as7Location);
    } catch (NamingException ne) {
    // Fall back and try for AS 4 ~ 6
    String legacyAsLocation = "java:/TransactionManager";

    try {
    // Check for JBoss AS 4 ~ 6
    return (TransactionManager) initialContext.lookup(legacyAsLocation);
    } catch (NamingException neAgain) {
    throw new ConfigurationException("Unable to locate a transaction manager in JNDI, either in " + as7Location + " or " + legacyAsLocation);
    }

    } finally {
    Util.close(initialContext);
    }
    }
    }

    在此就不再细说了,关键看另外一种在没有JBoss环境下的JTA事务管理该是怎样的。即配置Infinispan事务管理查找器为:JBossStandaloneJTAManagerLookup。看源码:

    /**
    * JTA standalone TM lookup.
    *
    *
    @author Jason T. Greene
    *
    @since 4.0
    */
    public class JBossStandaloneJTAManagerLookup implements TransactionManagerLookup {
    private Method manager, user;
    private static final Log log = LogFactory.getLog(JBossStandaloneJTAManagerLookup.class);

    @Inject
    public void init(Configuration configuration) {
    // The TM may be deployed embedded alongside the app, so this needs to be looked up on the same CL as the Cache
    try {
    manager = Util.loadClass("com.arjuna.ats.jta.TransactionManager", configuration.getClassLoader()).getMethod("transactionManager");
    user = Util.loadClass("com.arjuna.ats.jta.UserTransaction", configuration.getClassLoader()).getMethod("userTransaction");
    } catch (SecurityException e) {
    throw new RuntimeException(e);
    } catch (NoSuchMethodException e) {
    throw new RuntimeException(e);
    }
    }

    public TransactionManager getTransactionManager() throws Exception {
    TransactionManager tm = (TransactionManager) manager.invoke(null);
    if (log.isInfoEnabled()) log.retrievingTm(tm);
    return tm;
    }

    public UserTransaction getUserTransaction() throws Exception {
    return (UserTransaction) user.invoke(null);
    }
    }

    看上去似乎很简单,Infinispan使用该种方式也很简单,引入jbossjta.jar即可。如此对Infinispan缓存的事务管理功能就有了,但是有一个疑问,怎么与数据库的事务管理结合起来呢?我们知道之前《JBoss下的JTA使用理解》中借助JBoss容器只需配置数据源就可以了,这该怎么办呢?对事务类型有疑问可参看 事务处理总结(JDBC事务|JTA事务|容器事务

    继续

    让Infinispan使用JBoss JTA事务,引入jbossjta.jar,根据JTA规范,集成数据库的事务,应该让JDBC驱动实现JTA中参与者应该实现的接口,主要是XAResource,经测试MySQL JDBC驱动包括XA接口实现。之前是通过在JBoss中写好配置文件,从JNDI获取XA数据源,现在不借助JBoss容器,在应用中创建XADataSource,示例如下:

    package database.mysql.xa;

    import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;

    /**
    *
    @author yaohw
    *
    */
    public class XAUtil {

    public static MysqlXADataSource getXADataSource(){
    MysqlXADataSource xaDS = new MysqlXADataSource();
    xaDS.setDatabaseName("mytest");
    xaDS.setServerName("127.0.0.1");
    xaDS.setPortNumber(3306);
    xaDS.setUser("root");
    xaDS.setPassword("root");
    return xaDS;
    }

    public static void main(String[] args) {
    MysqlXADataSource xaDS = getXADataSource();
    System.out.println(xaDS);
    }
    }

    接着是重要的一步,该如何让JTA事务管理将该数据源的操作纳入到管理范围内。寻寻觅觅看到Transaction接口中有一个方法: boolean enlistResource(javax.transaction.xa.XAResource arg0),好!就是他了。同样还有一个相反的操作boolean delistResource(javax.transaction.xa.XAResource arg0, int arg1) 。

    具体获取连接以及XAResource的方式就比较简单,不赘述。
    接下来测试:

    try {
    tm.begin();
    value = cache.get(key);
    if(value == null){
    value = adminDAO.findAdminById(Integer.parseInt(key.toString()));
    cache.put(key, value);
    }
    System.out.println("get after put :"+cache.get(key));
    Admin a = new Admin();
    a.setPassword("hello");
    a.setUsername("boy");
    adminDAO.addAdmin(a);

    // rollback();
    tm.commit();
    System.out.println("get after rollback :"+cache.get(key));
    } catch (Exception e1) {
    e1.printStackTrace();
    rollback();
    }

    现在总算可以在离开JBoss的怀抱,数据库和缓存同生同灭了。

  • 相关阅读:
    查找路径php.ini文件到底在哪里?
    对象androidandroid 开发中 如何取得ListView 的 每条Item 的对象
    文件内容红帽子数据库.profile文件内容详解
    思维流程对测试认识的三个阶段
    磁盘修改RHEL6使用udev修改asm磁盘名
    环境错误Unable to add window token android.app.LocalActivityManager$LocalActivityRecord@435def20 is not v
    deployconfigurationJboss remote access
    数据级别[Oracle] 事务隔离级别(Oracle的实现方式)
    Linux 基本命令
    PostThreadMessage
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2348500.html
Copyright © 2020-2023  润新知