• XMLTable使用实践


    XMLTable使用实践

    最近在项目中遇到了一个使用XMLTable解决问题的实践。现总结如下:

    环境

    • DB:Oracle11g
    • ORM:iBatis

    BUG现象

    问题其实很简单,就是我们在项目中使用了很多超级长的SQL语句,之后导致SQL执行效率低下,并且貌似导致了Oracle的SQL编译空间益出了。

    出问题的SQL:

    SELECT N1,N2
    FROM A1
    WHERE
       
    N1='1' AND N2='a1') OR
       
    N1='2' AND N2='a2') OR
       
    N1='3' AND N2='a3') OR
       
    N1='4' AND N2='a4') OR
    ....省略2万行

    BUG解析

    当然了真实的SQL文是不可能这么简单的,比这个要复杂的多。不过出问题的部分基本就是这样了,其实原来没用AND/OR这种结构,用的是IN,但IN语句的参数不能超过2000个。所以就改成这个结构了,这个结构传东西到是没有限制了,但是会导致SQL文变长,而且由于数据的长度不定。这些1和a1是前面产生的结果,所以不一定有多少组。所以都是直接拼在SQL里了。问题很明显,后果很严重。

    BUG解决

    因为系统已经开发很长时间了,不能进行太大的改动。老系统就这样,改的越多,错的越多,狂改代码基本属于自虐行为。

    所以我们引入了XMLTable来解决这个问题,这还是一个DBA给的建议呢。

    SELECT N1,N2
    FROM A1
    WHERE
    (N1,N2) IN (
        SELECT X1
    ,X2 FROM
           
    XMLTable('for $i in /T/REC return $i' PASSING XMLType(#str:CLOB#)
            COLUMNS X1 INTEGER PATH
    'X1',
            X2 CHAR
    (2) PATH 'X2')

    因为使用iBatis的缘故,所以我使用了一个叫str的参数,并且声明为CLOB类型的,但str里放什么呢?

    <T>
       
    <REC><X1>1</X1><X2>a1</X2></REC>
       
    <REC><X1>2</X1><X2>a2</X2></REC>
        ....
    </T>

    这个很明白了吧,就是把需要的数据通过XML的形式变成一个表,之后再和主表进行子查询进行关联。这样做的好处就是把SQL文的长度变换为参数的长度了,虽然参数变长了,但SQL文本身变短了。

    总结

    真正做的时候还遇到了一些问题:

    首先,使用这个SQL的时候必须要在一个事务里,虽然他只是查询,但一定要在事务里否则会出错。

    因为咱们程序里使用了CLOB数据,所以要加载以下的Bean

    <bean id="simpleExtractor" 
         
    class="org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor">
    </bean>
    <bean id="oracleLobHandler"
         
    class="org.springframework.jdbc.support.lob.OracleLobHandler">
       
    <property name="nativeJdbcExtractor" ref="simpleExtractor"/>
    </bean>

    SQLMap里需要加一个CLOB的TypeHandler,之后在变量里声明一下#str:CLOB#就可是了。

    <typeHandler javaType="java.lang.String" jdbcType="CLOB"  
                 
    callback="org.springframework.orm.ibatis.support.ClobStringTypeHandler"/>

    但还有一点需要注意,我查了很长时间,因为$在iBatis里是关键字,这个关键字如果需要输出的话就需要转义,就要使用$代表一个$当然#也是同理的。

  • 相关阅读:
    每日日报110
    每日日报109
    每日日报108
    每日日报107
    每日日报106
    每日日报105
    每日日报104
    eclipse新建Maven Project项目后出现The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path问题的解决办法
    0proxy/reflect
    toRefs/toRef/unref/customRef
  • 原文地址:https://www.cnblogs.com/tjpanda88/p/2147543.html
Copyright © 2020-2023  润新知