java操作Oracle类型XMLType总结二:使用Mybatis

来源:互联网 发布:淘宝店铺月销量怎么看 编辑:程序博客网 时间:2024/05/29 17:52

上一篇我们已经成功用jdbc搞定了XMLType类型,这里将讲解如何用Mybatis来替代jdbc操作。

使用Mybatis操作XMLType,我们同样在Java端映射为String类型,当直接操作不做任何处理时,和jdbc大体一样,传输的内容长度小于4000时一切正常,当传输的内容长度超过4000左右时,同样抛出异常:ORA-01461: can bind a LONG value only for insert into a LONG column。

可见,Mybatis的操作其实和jdbc是一样的,只不过它在jdbc的外面又封装了一层,使得我们可以采用配置文件等映射的方式来更方便的访问数据库,我们要做的,就是在原有Mybatis便捷性的基础上实现对XMLType类型数据的插入,这种情况下,实现一个XMLType类型的自定义TypeHandler处理器是最好的选择。关于mybatis自定义转换器的实现,请移步[Mybatis实现自定义的类型转换器TypeHandler]

这里,我们仍然采用前面提到的方案三,自然那两个jar包:xdb.jar,xmlparserv2.jar也是要加入的。

添加一个XmltypeTypeHandler,实现TypeHandler接口,由于插入数据主要用到setParameter方法,所以这里只列出该方法,其它方法代码略:

    /**    * oracle SYS.XMLTYPE 类型自定义处理器    *    * User: liyd    * Date: 13-12-27    * Time: 下午4:53    */    public class XmltypeTypeHandler implements TypeHandler<String> {         @Override    public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {    }    ...    }


这个setParameter方法就是Mybatis在把数据插入到数据库时用来设置参数的,至于这个方法的参数相信你看代码也已经明白了,我们按照前面jdbc的实现方式,在这里插入如下代码:

    public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {    XMLType xmltype = XMLType.createXML(ps.getConnection(), parameter);    ps.setObject(i,xmltype);    }


并在mapper-config.xml中注册转换器,因为Mybatis定义的枚举org.apache.ibatis.type.JdbcType中,没有我们需要的XMLType类型,在这里我们定义为UNDEFINED:

    <configuration>    <typeHandlers>    <typeHandler javaType="string" jdbcType="UNDEFINED" handler="com.tyyd.dw.context.XmltypeTypeHandler"/>    </typeHandlers>    </configuration>


在配置文件参数中,使用我们的定义的转换器,这样Mybatis就能找到了:

  1. #{xmlFile,jdbcType=UNDEFINED},


当然你也可以更规范一点,完整的写出它的类型和使用的转换器:

  1. #{xmlFile,javaType=string,jdbcType=UNDEFINED,typeHandler=com.tyyd.dw.context.XmltypeTypeHandler},


完成上面的步骤,照理说一切都大功告成了,我们来运行一下。

结果抛出了异常:java.lang.ClassCastException: org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper cannot be cast to oracle.jdbc.OracleConnection

不能转换为Oracle的连接对象OracleConnection,查看一下,发现我们数据源使用的是apache的dbcp,应该是两者不兼容吧。网上查了一下,有位仁兄说是给了个完美解决文案,就是在setParameter方法内再独自加载一个Oracle的驱动类来创建一个connection,如下:

    Class.forName("oracle.jdbc.OracleDriver");    Connection connection = DriverManager.getConnection(url, username, password);


这个确实能100%解决连接对象不能转换的问题,但是实现方式上,呵呵,还是不做评论了。还有网上在传来传去的,说是可以转换成PoolableConnection 对象,再使用getDelegate方法可以获得原始代理链接,这个貌似可行,我们来试试:

    PoolableConnection connection = (PoolableConnection )ps.getConnection();    XMLType xmltype = XMLType.createXML(connection.getDelegate(), parameter);    ps.setObject(i,xmltype);


结果又抛出了异常:

org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper cannot be cast to org.apache.commons.dbcp.PoolableConnection,不能转换。

没办法,看来网上传来传去的文章不怎么可靠,没捷径了还是自己看看源代码吧。

通过查看源代码,我们发现PoolableConnection继承了DelegatingConnection类,而DelegatingConnection类实现了Connection接口,我们把它转换成DelegatingConnection试试:

    DelegatingConnection connection = (DelegatingConnection )ps.getConnection();    XMLType xmltype = XMLType.createXML(connection.getDelegate(), parameter);    ps.setObject(i,xmltype);


结果又抛出异常:无法构造描述符: Invalid arguments; nested exception is java.sql.SQLException: 无法构造描述符: Invalid arguments,通过断点调试,发现connection对象居然是null,怎么会是null呢,网上人家都用的好好的,到我这里就都不行了,真是蛋疼,这不会无解吧,难道真要像上面那位仁兄说的独自加载一个驱动类?没办法,再研究研究吧。

最后发现,通过getMetaData方法可以获取它的原始代理连接,柳暗花明啊,赶紧写上测试,终于正常了,不容易啊,最终代码如下:

    @Override    public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)    throws SQLException {    DelegatingConnection connection = (DelegatingConnection) ps.getConnection().getMetaData()    .getConnection();    XMLType xmltype = XMLType.createXML(connection.getDelegate(), parameter);    ps.setObject(i, xmltype);    }


至此,使用Mybatis操作XMLType类型终于是搞定了,过程是一波三折啊。数据有插入当然要有查询,接下来就要实现XMLType类型的查询操作了。

0 0
原创粉丝点击