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

10 篇文章 0 订阅

上一篇我们已经成功用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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值