diff --git a/pom.xml b/pom.xml index a44fd6a611..b88a36e085 100644 --- a/pom.xml +++ b/pom.xml @@ -412,7 +412,7 @@ com.h2database h2 - 1.3.167 + 1.3.168 test diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 7b6adf3a98..c592732e03 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -375,9 +375,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat this.dbType = JdbcUtils.getDbType(jdbcUrl, driverClass.getClass().getName()); } - if ("oracle".equals(this.dbType)) { - initOracle(); - } + initCheck(); initExceptionSorter(); initValidConnectionChecker(); @@ -510,16 +508,18 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat LOG.error(errorMessage + "validationQuery not set"); } - protected void initOracle() throws SQLException { - isOracle = true; + protected void initCheck() throws SQLException { + if (JdbcUtils.ORACLE.equals(this.dbType)) { + isOracle = true; - if (driver.getMajorVersion() < 10) { - throw new SQLException("not support oracle driver " + driver.getMajorVersion() + "." - + driver.getMinorVersion()); - } + if (driver.getMajorVersion() < 10) { + throw new SQLException("not support oracle driver " + driver.getMajorVersion() + "." + + driver.getMinorVersion()); + } - if (driver.getMajorVersion() == 10 && isUseOracleImplicitCache()) { - this.getConnectProperties().setProperty("oracle.jdbc.FreeMemoryOnEnterImplicitCache", "true"); + if (driver.getMajorVersion() == 10 && isUseOracleImplicitCache()) { + this.getConnectProperties().setProperty("oracle.jdbc.FreeMemoryOnEnterImplicitCache", "true"); + } } } diff --git a/src/main/java/com/alibaba/druid/pool/xa/DruidAXDataSource.java b/src/main/java/com/alibaba/druid/pool/xa/DruidXADataSource.java similarity index 57% rename from src/main/java/com/alibaba/druid/pool/xa/DruidAXDataSource.java rename to src/main/java/com/alibaba/druid/pool/xa/DruidXADataSource.java index 51b166c535..4c03b49559 100644 --- a/src/main/java/com/alibaba/druid/pool/xa/DruidAXDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/xa/DruidXADataSource.java @@ -11,40 +11,62 @@ import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.DruidPooledConnection; import com.alibaba.druid.support.logging.Log; import com.alibaba.druid.support.logging.LogFactory; +import com.alibaba.druid.util.H2Utils; import com.alibaba.druid.util.JdbcUtils; import com.alibaba.druid.util.MySqlUtils; import com.alibaba.druid.util.OracleUtils; import com.alibaba.druid.util.PGUtils; -public class DruidAXDataSource extends DruidDataSource implements XADataSource { +public class DruidXADataSource extends DruidDataSource implements XADataSource { - private final static Log LOG = LogFactory.getLog(DruidAXDataSource.class); + private final static Log LOG = LogFactory.getLog(DruidXADataSource.class); private static final long serialVersionUID = 1L; + private Object h2Factory = null; + @Override public XAConnection getXAConnection() throws SQLException { DruidPooledConnection conn = this.getConnection(); Connection physicalConn = conn.unwrap(Connection.class); - XAConnection rawXAConnection; + XAConnection rawXAConnection = createPhysicalXAConnetion(physicalConn); + + return new DruidPooledXAConnection(conn, rawXAConnection); + } + + protected void initCheck() throws SQLException { + super.initCheck(); + + if (JdbcUtils.H2.equals(this.dbType)) { + h2Factory = H2Utils.createJdbcDataSourceFactory(); + } + } + + private XAConnection createPhysicalXAConnetion(Connection physicalConn) throws SQLException { if (JdbcUtils.ORACLE.equals(dbType)) { try { - rawXAConnection = OracleUtils.OracleXAConnection(physicalConn); + return OracleUtils.OracleXAConnection(physicalConn); } catch (XAException xae) { LOG.error("create xaConnection error", xae); return null; } - } else if (JdbcUtils.MYSQL.equals(dbType)) { - rawXAConnection = MySqlUtils.createXAConnection(physicalConn); - } else if (JdbcUtils.POSTGRESQL.equals(dbType)) { - rawXAConnection = PGUtils.createXAConnection(physicalConn); - } else { - throw new SQLException("xa not support dbType : " + this.dbType); } - return new DruidPooledXAConnection(conn, rawXAConnection); + if (JdbcUtils.MYSQL.equals(dbType)) { + return MySqlUtils.createXAConnection(physicalConn); + } + + if (JdbcUtils.POSTGRESQL.equals(dbType)) { + return PGUtils.createXAConnection(physicalConn); + } + + if (JdbcUtils.H2.equals(dbType)) { + return H2Utils.createXAConnection(h2Factory, physicalConn); + } + + throw new SQLException("xa not support dbType : " + this.dbType); } @Override diff --git a/src/main/java/com/alibaba/druid/util/H2Utils.java b/src/main/java/com/alibaba/druid/util/H2Utils.java new file mode 100644 index 0000000000..35d9af3659 --- /dev/null +++ b/src/main/java/com/alibaba/druid/util/H2Utils.java @@ -0,0 +1,52 @@ +package com.alibaba.druid.util; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.sql.Connection; +import java.sql.SQLException; + +import javax.sql.XAConnection; + +import org.h2.jdbc.JdbcConnection; +import org.h2.jdbcx.JdbcDataSourceFactory; +import org.h2.jdbcx.JdbcXAConnection; +import org.h2.message.TraceObject; + +public class H2Utils { + + private static volatile Constructor constructor; + + private static volatile Method method; + + public static final int XA_DATA_SOURCE = 13; + + public static Object createJdbcDataSourceFactory() { + return new JdbcDataSourceFactory(); + } + + public static XAConnection createXAConnection(Object factory, Connection physicalConn) throws SQLException { + + try { + if (constructor == null) { + constructor = JdbcXAConnection.class.getConstructor(JdbcDataSourceFactory.class, int.class, + JdbcConnection.class); + constructor.setAccessible(true); + } + + int id = getNextId(XA_DATA_SOURCE); + + return constructor.newInstance(factory, id, physicalConn); + } catch (Exception e) { + throw new SQLException("createXAConnection error", e); + } + } + + public static int getNextId(int type) throws Exception { + if (method == null) { + method = TraceObject.class.getMethod("getNextId", int.class); + method.setAccessible(true); + } + + return (Integer) method.invoke(null, type); + } +} diff --git a/src/main/java/com/alibaba/druid/util/MySqlUtils.java b/src/main/java/com/alibaba/druid/util/MySqlUtils.java index 7f0e97ea99..ca58bc6da6 100644 --- a/src/main/java/com/alibaba/druid/util/MySqlUtils.java +++ b/src/main/java/com/alibaba/druid/util/MySqlUtils.java @@ -3,11 +3,13 @@ package com.alibaba.druid.util; import java.sql.Connection; import java.sql.SQLException; +import javax.sql.XAConnection; + import com.mysql.jdbc.jdbc2.optional.MysqlXAConnection; public class MySqlUtils { - public static MysqlXAConnection createXAConnection(Connection physicalConn) throws SQLException { + public static XAConnection createXAConnection(Connection physicalConn) throws SQLException { return new MysqlXAConnection((com.mysql.jdbc.ConnectionImpl) physicalConn, false); } } diff --git a/src/main/java/com/alibaba/druid/util/OracleUtils.java b/src/main/java/com/alibaba/druid/util/OracleUtils.java index 139f5e949c..3ef1bbfd2f 100644 --- a/src/main/java/com/alibaba/druid/util/OracleUtils.java +++ b/src/main/java/com/alibaba/druid/util/OracleUtils.java @@ -5,6 +5,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import javax.sql.XAConnection; import javax.transaction.xa.XAException; import oracle.jdbc.OracleConnection; @@ -19,7 +20,7 @@ import com.alibaba.druid.pool.DruidPooledPreparedStatement; public class OracleUtils { - public static OracleXAConnection OracleXAConnection(Connection oracleConnection) throws XAException { + public static XAConnection OracleXAConnection(Connection oracleConnection) throws XAException { return new OracleXAConnection(oracleConnection); } diff --git a/src/main/java/com/alibaba/druid/util/PGUtils.java b/src/main/java/com/alibaba/druid/util/PGUtils.java index 52ba89b66a..b9f7e71c89 100644 --- a/src/main/java/com/alibaba/druid/util/PGUtils.java +++ b/src/main/java/com/alibaba/druid/util/PGUtils.java @@ -3,12 +3,14 @@ package com.alibaba.druid.util; import java.sql.Connection; import java.sql.SQLException; +import javax.sql.XAConnection; + import org.postgresql.core.BaseConnection; import org.postgresql.xa.PGXAConnection; public class PGUtils { - public static PGXAConnection createXAConnection(Connection physicalConn) throws SQLException { + public static XAConnection createXAConnection(Connection physicalConn) throws SQLException { return new PGXAConnection((BaseConnection) physicalConn); } }