TangYuan之组合SQL服务标签

作者: xsonorg | 来源:发表于2016-12-17 21:01 被阅读49次

6.4 组合SQL服务标签


之前6.1节简单的介绍了组合SQL服务的概念和定义,这节将详细的介绍组合SQL服务的功能和使用。

1. sql-service标签的使用

Schema设计图

图片1

sql-service节点属性说明

属性名 用途及说明 必填 取值
id 服务标识,需要唯一;作为辅助标签此项无意义,可省略 Y 用户定义
dsKey 所使用的数据源标识,这里有以下几种情况:<br />1.此处设置数据源(A),内部服务未设置数据源,内部服务使用数据源(A)。<br />2.此处设置数据源(A),内部服务设置数据源(B),内部服务使用数据源(B)。<br />3.此处未设置数据源,内部服务设置数据源(B),内部服务使用数据源(B)。<br />4.在分库分表的情况下,此处未和内部服务均可不设置数据源,后面章节将会详细介绍此种设置。 N 用户定义
txRef 所使用的事务定义标识,如果用户未指定,则根据setDefaultTransaction所定义的规则进行默认匹配,如果还未匹配上,系统则会跑出异常。 N 用户定义
resultType 返回类型:默认xco N xco/map
cacheUse 缓存使用,此项将在缓存一节详细说明 N 用户定义
cacheClear 缓存使用,此项将在缓存一节详细说明 N 用户定义

说明:

组合SQL服务是一个服务集合,他可以包含selectSetselectOneselectVarupdatedeleteinsert这6中基本服务标签一个或者多个,但不能包含自身sql-service标签。

2. 内部selectSet标签的使用

示例1:

<sql-service id="myService" dsKey="ds" txRef="tx_02">
    <selectSet resultKey="{users}">
        select * from user
    </selectSet>
    <return>
        <property value="{users}"/>
    </return>
</sql-service>

说明:

上述示例中我们定义了一个组合SQL服务myService,其内部包含了了一个selectSet基本服务,当程序执行完selectSet服务后会将其结果List<XCO>以users为key,放入上下文中,最后通过return标签返回。具体的返回结果是一个XCO对象,其中包含一个List<XCO>元素,关于return标签和返回结果的设定我们将在其他章节讲述,这里不再细说,下面给出返回结果的XML格式。

返回结果

<?xml version="1.0" encoding="UTF-8"?>
<X>
    <XL K="users">
        <X>
            <L K="user_id" V="1"/>
            <S K="user_name" V="李四"/>
            <B K="user_age" V="18"/>
            <A K="create_time" V="2016-10-20 21:30:58"/>
        </X>
        <X>
            <L K="user_id" V="2"/>
            <S K="user_name" V="张三"/>
            <B K="user_age" V="18"/>
            <A K="create_time" V="2016-10-20 21:31:58"/>
        </X>
        ......
    </XL>
</X>

上述示例中selectSet作为内部服务,或者说内部标签,其属性的使用发生了一下变化:

selectSet节点属性和变化说明:

属性名 用途及说明 必填 取值
id 无意义 N 用户定义
dsKey 所使用的数据源标识,在有如下几种情况(非分库分表):<br />1.如果用户没有设置此属性,则使用sql-service节点的数据源;<br />2.如果用户自行设置了此属性,则使用用户所设置的数据源。<br />关于在分库分表的应用场景下,此项的设置我们将在具体的章节来说明。 N 用户定义
txRef 无意义 N 用户定义
resultKey 当前查询操作返回结果的在上下文参数中的存放key N 用户定义
resultType 无意义 N 用户定义
resultMap 无意义 N 用户定义
fetchSize 每次查询的最大获取条数,默认255 N 用户定义
cacheUse 缓存使用,此项将在缓存一节详细说明 N 用户定义

看到这里大家可能会疑问,和示例1中,为什么不直接用selectSet标签呢?因为之前已经给已经给大家介绍过sql-service所定义的服务是一个组合服务,其内部可以包含selectSetselectOneselectVarupdatedeleteinsert这些基本服务,在后面的教程中大家就可以感受到组合服务的强大功能了。

2. 内部selectOne标签的使用

示例2:

<sql-service id="myService2" dsKey="ds" txRef="tx_02">
    <selectOne resultKey="{user}">
        select * from user where user_id = #{user_id}
    </selectOne>
    <return value="{user}"/>
</sql-service>

说明:

示例2中我们定义了一个组合SQL服务myService2,其内部包含了了一个selectOne基本服务,执行后返回结果是一个XCO对象,XML格式如下:

返回结果

<X>
    <L K="user_id" V="1"/>
    <S K="user_name" V="李四"/>
    <B K="user_age" V="18"/>
    <A K="create_time" V="2016-10-20 21:30:58"/>
</X>

selectOne节点属性和变化说明:

属性名 用途及说明 必填 取值
id 无意义 N 用户定义
dsKey 同selectSet.dsKey N 用户定义
txRef 无意义 N 用户定义
resultKey 当前查询操作返回结果的在上下文参数中的存放key N 用户定义
resultType 无意义 N 用户定义
resultMap 无意义 N 用户定义
fetchSize 每次查询的最大获取条数,默认255 N 用户定义
cacheUse 缓存使用,此项将在缓存一节详细说明 N 用户定义

3. 内部selectVar标签的使用

示例3:

<sql-service id="myService3" dsKey="ds" txRef="tx_02">
    <selectVar resultKey="{userName}">
        select user_name from user where user_id = #{user_id}
    </selectVar>
    <return>
        <property name="{userName}" value="{userName}"/>
    </return>
</sql-service>

说明:

示例3中我们定义了一个组合SQL服务myService3,其内部包含了了一个selectVar基本服务,执行后返回结果是一个XCO对象,其中包含了一个userName元素,XML格式如下:

返回结果

<?xml version="1.0" encoding="UTF-8"?>
<X>
    <S K="userName" V="李四"/>
</X>

selectVar节点属性和变化说明:

属性名 用途及说明 必填 取值
id 无意义 N 用户定义
dsKey 同selectSet.dsKey N 用户定义
txRef 无意义 N 用户定义
resultKey 当前查询操作返回结果的在上下文参数中的存放key N 用户定义
cacheUse 缓存使用,此项将在缓存一节详细说明 N 用户定义

4. 内部update标签的使用

示例4:

<sql-service id="myService4" dsKey="ds" txRef="tx_02">
    <update rowCount="{nCount}">
        update user set user_name = '张三' where user_id = #{user_id}
    </update>
    <exception test="{nCount} != 1" code="-1" message="用户更新失败"/>
</sql-service>

说明:

示例4中我们定义了一个组合SQL服务myService4,其内部包含了了一个update基本服务,当程序执行完update服务后会将影响行数以nCount为key,放入上下文中,然后通过exception标签判断nCount的有效性,如果nCount不满足条件,则无服务将抛出服务异常,并回滚之前的操作。

返回结果: 无

update节点属性和变化说明:

属性名 用途及说明 必填 取值
id 无意义 N 用户定义
dsKey 同selectSet.dsKey N 用户定义
txRef 无意义 N 用户定义
rowCount 当前更新操作的影响行数的在上下文参数中的存放key N 用户定义
cacheClear 缓存使用,此项将在缓存一节详细说明 N 用户定义

5. 内部delete标签的使用

示例5:

<sql-service id="myService5" dsKey="ds" txRef="tx_02">
    <delete rowCount="{nCount}">
        delete from user where user_id = #{delete_user_id}
    </delete>
    <exception test="{nCount} != 1" code="-1" message="用户删除失败"/>
</sql-service>

说明

示例5中我们定义了一个组合SQL服务myService5,其内部包含了了一个delete基本服务,当程序执行完delete服务后会将影响行数以nCount为key,放入上下文中,然后通过exception标签判断nCount的有效性,如果nCount不满足条件,则无服务将抛出服务异常,并回滚之前的操作。

返回结果: 无

delete节点属性和变化说明:

属性名 用途及说明 必填 取值
id 无意义 N 用户定义
dsKey 同selectSet.dsKey N 用户定义
txRef 无意义 N 用户定义
rowCount 当前更新操作的影响行数的在上下文参数中的存放key N 用户定义
cacheClear 缓存使用,此项将在缓存一节详细说明 N 用户定义

6. 内部insert标签的使用

示例6:

<sql-service id="myService6" dsKey="ds" txRef="tx_02">
    <insert incrementKey="{user_id}" rowCount="{nCount}">
        insert into user(user_name, user_age, create_time) values('李四', 26, #{create_time|now()});
    </insert>
    <return>
        <property value="{user_id}"/>
        <property value="{nCount}"/>
    </return>
</sql-service>

说明:

示例6中我们定义了一个组合SQL服务myService6,其内部包含了了一个insert基本服务,当程序执行完insert服务后会作2个操作:第一,将insert语句自动生成的主键以user_id为key,放入上下文中;第二将影响行数以nCount为key,放入上下文中,然后通过return标签将其返回,XML格式如下:

返回结果

<?xml version="1.0" encoding="UTF-8"?>
<X>
    <L K="user_id" V="10"/>
    <I K="nCount" V="1"/>
</X>

insert节点属性和变化说明:

属性名 用途及说明 必填 取值
id 无意义 N 用户定义
dsKey 同selectSet.dsKey N 用户定义
txRef 无意义 N 用户定义
resultType 无意义 N 用户定义
rowCount 当前更新操作的影响行数的在上下文参数中的存放key N 用户定义
incrementKey 当前插入操作返回插入后的主键(数据库自动生成的)的在上下文参数中的存放key。<br />关于返回主键,有以下几种情况:<br />3.插入一条记录,返回单个主键,其结果类型视主键的数据库数据类型而定。<br />2. 插入多条记录,返回多个主键数组,数组元素类型视主键的数据库数据类型而定。 N 用户定义
cacheClear 缓存使用,此项将在缓存一节详细说明 N 用户定义

之前我们看到的示例都是一些很简单的组合SQL服务,下面我们看一个复杂的组合SQL服务示例。

7. 组合SQL的使用

示例7

<sql-service id="myService7" dsKey="ds" txRef="tx_02">
    <selectSet resultKey="{users}">
            select * from user
    </selectSet>
    
    <selectOne resultKey="{user}">
        select * from user where user_id = #{user_id}
    </selectOne>
    
    <selectVar resultKey="{userName}">
        select user_name from user where user_id = #{user_id}
    </selectVar>
    
    <update rowCount="{nCount}">
        update user set user_name = '张三' where user_id = #{user_id}
    </update>
    <exception test="{nCount} != 1" code="-1" message="用户更新失败"/>
    
    <delete rowCount="{nCount}">
        delete from user where user_id = #{delete_user_id}
    </delete>
    <exception test="{nCount} != 1" code="-1" message="用户删除失败"/>    
        
    <insert incrementKey="{user_id}" rowCount="{nCount}">
        insert into user(user_name, user_age, create_time) values('李四', 26, #{create_time|now()});
    </insert>
    
    <return>
        <property value="{users}"/>
        <property value="{user}"/>
        <property value="{userName}"/>
        <property value="{user_id}"/>
    </return>            
        
</sql-service>

返回结果:

<?xml version="1.0" encoding="UTF-8"?>
    <X>
        <XL K="users">
            <X>
                <L K="user_id" V="1"/>
                <S K="user_name" V="张三"/>
                <B K="user_age" V="18"/>
                <A K="create_time" V="2016-10-20 21:30:58"/>
            </X>
            <X>
                <L K="user_id" V="2"/>
                <S K="user_name" V="张三"/>
                <B K="user_age" V="18"/>
                <A K="create_time" V="2016-10-20 21:31:58"/>
            </X>
            ...
        </XL>
        <X K="user">
            <L K="user_id" V="1"/>
            <S K="user_name" V="张三"/>
            <B K="user_age" V="18"/>
            <A K="create_time" V="2016-10-20 21:30:58"/>
        </X>
        <S K="userName" V="张三"/>
        <L K="user_id" V="11"/>
    </X>

说明:

示例7其实就是整合之前的示例1到示例6,在一个服务中完成6个操作,并根据需要返回结果,就如同SQL中的存储过程,Java中的函数一般,这才是组合SQL服务的优势所在,通过一些基本服务的组合,和一些辅助标签,实现复杂的业务逻辑。使其开发人员即使不懂的JAVA也可完成大部分的服务开发工作。

8. 自定义返回结果

在组合SQL服务中可以通过return标签来定义返回内容。return标签的使用一般有下面两种情况:

示例8:

<sql-service id="myService" dsKey="ds" txRef="tx_02">
    <selectSet resultKey="{users}">
        select * from user
    </selectSet>
    <return>
        <property value="{users}"/>
    </return>
</sql-service>

说明:

示例8中return标签表示返回一个封装后的对象(默认为XCO类型),此对象中包含一个名为users的属性,值为List<XCO>

示例9:

<sql-service id="myService" dsKey="ds" txRef="tx_02">
    <selectVar resultKey="{userName}">
        select user_name from user where user_id = #{user_id}
    </selectVar>
    <return value="{userName}" />
</sql-service>

说明:

示例9中return标签表示直接返回userName所代表的值,此处为userName的类型为String

上述两个示例说明了return标签的两种使用方式,一种是返回一个封装对象,然后通过property子标签定义其内部具体属性和属性值。另一种是直接通过return标签的value属性定义返回值,在这种情况下的返回类型由value属性中的变量所代表的值的类型来决定。注意,这两种方式不能混合使用,当然如果某个服务不需要返回类型,也可以不使用return标签,但是如果使用return标签,则只能有一个。

Schema设计图

图片2

return节点属性说明:

属性名 用途及说明 必填 取值
value 需要直接返回的变量名称, 如value="{user}" N 用户定义

property节点属性说明:

属性名 用途及说明 必填 取值
name 返回对象中的属性名称,可省略,默认为value中的变量名称 N 用户定义
value 代表属性值的变量名称 Y 用户定义

10. log标签的使用

日志打印标签,用于在服务执行过程中的检测和日志的输出。

示例10:

<sql-service>
    <log message="更新用户:开始" level="info"/>
    <update rowCount="{nCount}">...</update>
    <log message="更新用户:结束"/>
    <log message="更新班级:开始"/>
    <update rowCount="{nCount}">...</update>
    <log message="更新班级:结束"/>
</sql-service>

说明:

上述示例中使用4个log标签,分别在update操作前后,这样开发的时候可以方便的从日志中观察到服务的执行情况。

Schema设计图

图片3

log节点属性说明:

属性名 用途及说明 必填 取值
message 日志内容,其中可使用变量;如:<log message="学生ID: {user_id}, 班级ID: {class_id}"/> Y 用户定义
level 日志等级默认info,可参考log4j的日志等级 N error/warn/info/debug

11. setvar标签的使用

用途:变量设置标签,在XML中给一个变量赋值。

示例11:

<sql-service>
    <setvar key="{x}" value="0"/>
    <if test="{type} == 1">
        <selectOne resultKey="{x}">....</selectOne>
    </if>
    <return>
        <property value="{x}"/>
    </return>
</sql-service>

说明:

上述示例中先将比变量x赋值为0,然后判断条件,如果type==1,则执行selectOne操作,将执行结果重新赋值给变量x,最后返回x.

Schema设计图

图片4

setvar节点属性说明:

属性名 用途及说明 必填 取值
key 变量名称,如:key="{x}" Y 用户定义
value 变量值 Y 用户定义
type 变量的数据类型,默认将会根据根据用户输入变量值自动分析其类型;比如:<br />value="0",类型为int<br />value="1.3",类型为float<br />value="true",类型为boolean<br />value="xxx",类型为String<br />value="yyyy-MM-dd HH:mm:ss",类型为dateTime<br />value="yyyy-MM-dd",类型为date<br />value="HH:mm:ss",类型为time N int<br />long<br />float<br />double<br />short<br />boolean<br />byte<br />char<br />dateTime<br />date<br />time<br />

12. transGroup标签的使用

transGroup的作用就是启动一个新的事务,如果transGroup中的服务执行失败将不会影响之前的事务。

示例12:

<sql-service id="myService" dsKey="ds" txRef="tx_02">
    <update rowCount="{nCount}">
        update user set user_name = '张三' where user_id = #{user_id}
    </update>
    <transGroup txRef="tx_03">        <!-- (1) -->
        <insert incrementKey="{user_id}" rowCount="{nCount}">
            insert into user(user_name, user_age, create_time) values('李四', 26, #{create_time|now()});
        </insert>        
    </transGroup>                    <!-- (2) -->
    <update rowCount="{nCount}">    <!-- (3) -->
        update user set user_name = '李四' where user_id = #{user_id}
    </update>        
    <return>...</return>
</sql-service>

说明:

上述示例中服务执行到(1)的时候,根据transGroup所使用事务定义tx_03,启动一个新事物Y,并将之前的事务X挂起,开始执行其内部的insert服务,如果顺利的执行到(2)的位置,则提交事物Y,并恢复之前的X,继续执行后面的操作;一旦在此期间发生异常,则回滚事物Y,恢复之前的事物X,从(3)的位置继续执行。

注意:transGroup所使用的事务定义的传播属性必须是requires_new或者not_supported

Schema设计图

图片5

transGroup节点属性说明:

属性名 用途及说明 必填 取值
txRef 所引用事务定义的id Y 用户定义

13. call标签的使用

服务内部调用标签,就是在一个组合服务内部调用其他服务,可以是基本服务,也可以是另一个组合服务。

示例13A:

<selectOne id="getUserById">
    SELECT * from user WHERE user_id = #{user_id}
</selectOne>

<sql-service id="myService" dsKey="ds" txRef="tx_02">
    <update rowCount="{nCount}">
        update user set user_name = '张三' where user_id = #{user_id}
    </update>
    <call service="demo2.getUserById" resultKey="{user}"/>
    <return>
        <property value="{user}"/>
    </return>
</sql-service>    

说明:

上述示例中在myService内部调用了getUserById服务,调用指的是像JAVA函数之间的调用一样,有入参,有返回。当执行完call标签后,会将其执行结果以user为key放入参数上下文中。细心的同学可能会有疑问,getUserById服务是需要一个user_id参数的,如何获取其值呢?其实在上述示例中myService隐示的将自己的上下文和参数传递给getUserByIdmyService的参数中是存在user_id,所以getUserById服务可以顺利取到值。

通过下面这种方式,我们还可以显示的给getUserById服务传递参数:

示例13B:

<call service="demo2.getUserById" resultKey="{user}">
    <property value="{user_id}"/>
</call>

在这中方式下,调用getUserById服务的时候仅仅给其传递了user_id一个参数。

示例13C:

<call service="demo2.getUserById" resultKey="{user}" mode="EXTEND" exResultKey="{ex}"/>

说明:

示例13C中call标签出现了mode属性和exResultKey属性,mode属性表示的是调用的模式,exResultKey属性表示的是当调用发生异常后,将异常信息的codemessage封装成一个新的对象(默认为XCO对象),以ex为key放入参数上下文中,供后续程序使用。

注意: 要避免循环或递归调用。

Schema设计图

图片6

call节点属性说明:

属性名 用途及说明 必填 取值
service 被调用的服务名称。格式为:命名空间+"."+服务id Y 用户定义
resultKey 返回结果的key N 用户定义
mode 调用模式,默认EXTEND<br />EXTEND:被调用方将继承调用方的上下文。<br />ALONE:被调用方有独立的上下文。<br />ASYNC:异步调用,被调用方有独立的上下文。 N EXTEND/ALONE/ASYNC
exResultKey 调用过程中发生异常后,将异常信息封装成对象codemessage所存放的key N 用户定义

property节点属性说明:

属性名 用途及说明 必填 取值
name 参数名,默认为value的变量名 N 用户定义
value 参数值 Y 用户定义

14. exception标签的使用

异常标签,当满足其检测条件的时候会抛出服务异常ServiceException

示例14:

<sql-service id="myService4" dsKey="ds" txRef="tx_02">
    <update rowCount="{nCount}">......</update>
    <exception test="{nCount} != 1" code="-1" message="用户更新失败"/>
    ......
</sql-service>

说明:

对于exception标签的使用之前已经有过很多示例,这里我们着重介绍一些服务异常抛出后相关的处理,一般有以下几种情况:

  1. 当前上下文中运行这一个事务,对于这种情况tangyuan框架捕捉到异常后会先回滚当前事务,然后在将此异常继续上抛给调用方。对于调用方捕获到服务异常后可通过ServiceException对象的getErrorCode和getErrorMessage拿到错误码和错误描述。
  2. 当前上下文中存在挂起的事务,也就是说当前操作运行在一个独立的事务中,在这种情况下框架捕捉到异常后会先回滚当前事务,然后恢复最近挂起的服务,并继续执行。

Schema设计图

图片7

exception节点属性说明:

属性名 用途及说明 必填 取值
test 逻辑表达式,同if标签的test属性。 Y 用户定义
code 当抛出服务异常时所携带的错误码。 N 用户定义
message 当抛出服务异常时所携带的错误描述。 N 用户定义

到此,第六章节的内容就结束了,感兴趣的朋友可以关注TangYuan项目。

相关文章

  • TangYuan之组合SQL服务标签

    6.4 组合SQL服务标签 之前6.1节简单的介绍了组合SQL服务的概念和定义,这节将详细的介绍组合SQL服务的功...

  • TangYuan之基本SQL服务标签

    6.2 基本SQL服务标签 1. selectSet标签 示例: 说明 上面示例表示我们定义了一个ID为getUs...

  • TangYuan之SQL服务及标签介绍

    6.1 SQL服务及标签介绍 什么是SQL服务?SQL服务的本质是一个服务,包含了一系列的SQL语句和XML标签。...

  • Tangyuan介绍

    tangyuan 1. 项目介绍 TangYuan是一个基于Java的持久层框架。提供的持久层框架包括SQL Ma...

  • TangYuan之XML介绍

    TangYuan之XML介绍 1. Tangyuan中的XML文件 使用Tangyuan框架开发是通过配置和编写一...

  • TangYuan之辅助标签使用

    6.3 辅助标签使用 1.If/elseif/else标签的使用 示例1: 说明 示例1是一个经典条件组合查询场景...

  • Mybatis之foreach标签使用方法

    MyBatis动态sql之foreach标签 Mybatis之foreach标签使用方法,Mybatis之fore...

  • TangYuan之Ognl设计

    TangYuan之Ognl设计 前言: 本文中的内容需要读者对tangyuan框架和XCO对象有一定的了解和使用经...

  • TangYuan之插件使用

    TangYuan之插件使用 Tangyuan中可以通过插件来实现和扩充其功能,按用途可分为3种: 数据和结果映射插...

  • TangYuan之数据源

    TangYuan之数据源 1. 简介 Tangyuan中数据源配置分为两种,一种是普通数据源,适用于普通的数据库应...

网友评论

    本文标题:TangYuan之组合SQL服务标签

    本文链接:https://www.haomeiwen.com/subject/jmhamttx.html