Mybatis JDBC访问 Oracle的XMLType数据类型



Mybatis JDBC访问 Oracle的XMLType数据类型。这就是我要做的,用XML作为JAVA和数据库交流的载体。粗想一下是有些些反人类,不过如果能一次性取出多条多种数据集,也算是个不错的选择吧。本篇不深究是否值得这么去折腾,蛋,如果有一天你必须去面对这个无情的事实的时候,可以用下面的法子试试看。以下用Mybatis实现的,其实直接JDBC的访问也是一样的,本例只不过借用Mybatis搭好的架子而已。
先简单说说你需要的Java环境:JDK 5 以上,Oracle10G版本以上的驱动(我用的ojdbc6.jar),访问Oracle XMLType的组件包–xdb6.jar xmlparserv2.jar,还有就是DAO的—mybatis-3.2.0
这些包基本都可以从各自的官方获得,特别说一下xmlparserv2.jar,这傻逼玩意儿需要下载Oracle的开发工具比如SQLDeveloper之类的之后,在其内部寻找。Oracle官方没有直接下载的地儿——决逼坑爹!

好了开始:
1。先做一个用于处理XMLType的TypeHandler以便Mybatis识别你要处理的类型。

[java] view plaincopy
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLXML;

import oracle.sql.OPAQUE;
import oracle.xdb.XMLType;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

public class XMLTypeHandler extends BaseTypeHandler<SQLXML> {

@Override
public void setNonNullParameter(PreparedStatement ps, int i, SQLXML parameter, JdbcType jdbcType) throws SQLException {
ps.setSQLXML(i, parameter);
}

@Override
public SQLXML getNullableResult(ResultSet rs, String columnName) throws SQLException {
return getXMLType(rs.getObject(columnName));
}

@Override
public SQLXML getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return getXMLType(rs.getObject(columnIndex));
}

@Override
public SQLXML getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return getXMLType(cs.getObject(columnIndex));
}

private SQLXML getXMLType(Object obj) throws SQLException {
OPAQUE o = (OPAQUE)obj;
XMLType xt = XMLType.createXML(o);
return xt;
}
}

2。Mybatis暂时还不支持XMLType也就是OPAQUE,我想以后的版本也许会支持。所以你需要想个办法让他暂时支持。这步没啥好办法,Mybatis用的枚举,这玩意儿不能继承,只能耍耍流氓了,把源代码Copy出来做如下处理:

实际就加了一个枚举值。
[java] view plaincopy
* Copyright 2009-2012 The MyBatis Team
package org.apache.ibatis.type;


import java.sql.Types;

public enum JdbcType {
/*
* This is added to enable basic support for the
* ARRAY data type – but a custom type handler is still required
*/
ARRAY(Types.ARRAY),
BIT(Types.BIT),
TINYINT(Types.TINYINT),
SMALLINT(Types.SMALLINT),
INTEGER(Types.INTEGER),
BIGINT(Types.BIGINT),
FLOAT(Types.FLOAT),
REAL(Types.REAL),
DOUBLE(Types.DOUBLE),
NUMERIC(Types.NUMERIC),
DECIMAL(Types.DECIMAL),
CHAR(Types.CHAR),
VARCHAR(Types.VARCHAR),
LONGVARCHAR(Types.LONGVARCHAR),
DATE(Types.DATE),
TIME(Types.TIME),
TIMESTAMP(Types.TIMESTAMP),
BINARY(Types.BINARY),
VARBINARY(Types.VARBINARY),
LONGVARBINARY(Types.LONGVARBINARY),
NULL(Types.NULL),
OTHER(Types.OTHER),
BLOB(Types.BLOB),
CLOB(Types.CLOB),
BOOLEAN(Types.BOOLEAN),
CURSOR(-10), // Oracle
UNDEFINED(Integer.MIN_VALUE + 1000),
NVARCHAR(-9), // JDK6
NCHAR(-15), // JDK6
NCLOB(2011), // JDK6
STRUCT(Types.STRUCT),
SQLXML(Types.SQLXML),
OPAQUE(OracleTypes.OPAQUE);

public final int TYPE_CODE;
private static Map<Integer,JdbcType> codeLookup = new HashMap<Integer,JdbcType>();

static {
for (JdbcType type : JdbcType.values()) {
codeLookup.put(type.TYPE_CODE, type);
}
}

JdbcType(int code) {
this.TYPE_CODE = code;
}

public static JdbcType forCode(int code) {
return codeLookup.get(code);
}

}

3。在Mybatis的配置文件中注册XMLType的Handler
[html] view plaincopy
<typeHandlers>
<typeHandler
javaType=”java.sql.SQLXML”
handler=”com.core.db.typehandler.XMLTypeHandler”
/>
</typeHandlers>

4。在Mybatis的SQL配置文件中使用XMLType,例子是呼叫了一个存储过程。
[html] view plaincopy
<update id=”selectProperty” parameterType=”map” statementType=”CALLABLE”>
{
call pkg.select_proc(
#{id, mode=IN, jdbcType=NUMERIC}
, #{results, mode=INOUT, javaType=java.sql.SQLXML, jdbcType=OPAQUE, jdbcTypeName=XMLTYPE}
)
}
</update>
5。如何从JAVA侧传入XMLType的参数到Oracle

[java] view plaincopy
Connection conn = session.getConnection();
SQLXML sqlXml = conn.createSQLXML();
sqlXml.setString(strXML);

dbMapper.testXMLType(paramMap);

6。如何取得Oralce返回的XMLType
[java] view plaincopy
SQLXML sqlXml = (SQLXML)paramMap.get(“results”);
System.out.println(sqlXml.getString());

完活儿!
另外变通写的做法也有,就是在数据库侧用XMLType(CLOB)等方式改写自己的SQL然后用CLOB等数据结构调用。不过,男人嘛就要对自己残忍一些,XML直接上,必须的!

http://blog.csdn.net/lj0425/article/details/7886613