iBATIS一对多查询

iBATIS框架也提供了多种方法用以关联复杂的对象,比如订单(order)和它的订单项(order item)(还有它们的相关产品、顾客等等)。每种方法都有其优点和缺点,正所谓“尺有所短,寸有所长”,每一种方案都不是完美的。应根据需要来选择适合的方案。

注意:为简短起见,在本章的余下的例子中,我们将省略那些对于演示来说不必要的数据。例如,当我们获取了一个顾客(customer)对象,我们不会获取它的所有字段,而是仅仅获取它的主键和外键。

复杂的集合属性

在第4章中,我们学习了如何使用SELECT语句从数据库获取数据。在那些例子中,我们获取的结果仅仅是单个对象,即使是连接多表也是如此。事实上,如果您有多个复杂对象,也可以使用iBATIS加载它们。

如果我们的应用程序模型与数据模型比较类似,那么这个功能会很有用。可以考虑根据对象的关系(关联)来定义数据模型,然后使用iBATIS将它们一起加载。例如,如果在数据库中,Account记录对应着相关的Order记录,而Order又对应着相关的OrderItem记录,可以为这些记录建立关系,当我们请求一条Account记录时,可以一并获取所有的Order和OrderItem记录。下面的代码清单显示了如何定义我们的SQL映射:
 
<resultMap id="ResultAccountInfoMap" class="AccountInfo">
<result property="accountId"
column="accountId" />
<result property="orderList"
select="Ch6.getOrderInfoList"
column="accountId" />
</resultMap>
<resultMap id="ResultOrderInfoMap" class="OrderInfo">
<result property="orderId" column="orderId" />
<result property="orderItemList" column="orderId"
select="Ch6.getOrderItemList" />
</resultMap>
<resultMap id="ResultOrderItemMap" class="OrderItem">
<result property="orderId" column="orderId" />
<result property="orderItemId" column="orderItemId" />
</resultMap>

<select id="getAccountInfoList" resultMap="ResultAccountInfoMap" >
select accountId from Account
</select>
<select id="getOrderInfoList" resultMap="ResultOrderInfoMap">
select orderId from orders
where accountId = #value#
</select>
<select id="getOrderItemList" resultMap="ResultOrderItemMap">
select orderId, orderItemId from orderItem
where orderid = #value#
</select>
 

先来看看结果映射(result map,即上面的ResultAccountInfoMap,ResultOrderInfoMap和ResultOrderItemMap),前两个Map都用到了select特性。这个特性告诉iBATIS,属性的值将由另一个映射语句来设置,语句的名称就是select特性的值。例如,我们执行getAccountInfoList语句时,ResultAccountInfoMap结果映射有一个子元素:
iBATIS一对多查询<resultproperty="orderList" select="Ch6.getOrderInfoList" column="accountId" />

它的作用是告诉iBATIS,account对象的orderList属性的值由Ch6.getOrderInfoList语句来设置,同时把accountId列的值传给Ch6.getOrderInfoList作为参数。类似地,在设置order对象的orderItemList对象时,也会执行getOrderItemList语句。

这个功能给我们带来便利的同时,也带来了两个问题。首先,创建包含大量对象的列表可能会消耗大量的内存。其次,这种方法会导致数据库的I/O问题,其原因是所谓的“N+1 Select”现象,这个现象将在后面讨论。对于每个问题,iBATIS框架都提供了解决方案,但是注意,没有哪一种能同时解决这两个问题。

数据库I/O

数据库I/O是数据库使用状况的一项指标,也是数据库性能的主要瓶颈之一。在读取或写入数据库时,数据必须要经历从磁盘到内存或者从内存到磁盘的转换,这个过程是比较耗时的。在程序中使用缓存可以减少对数据库的访问,但这种方法使用时要谨慎,否则也会引发问题。要了解iBATIS中的缓存机制,可以参看第10章的内容。

在使用关联数据时,可能会遭遇数据库I/O问题。考虑一下这个场景:有1000个Account,每一个关联了1000个Order,而每个Order则包含25个OrderItem。如果尝试将所有这些数据加载到内存,执行的SQL语句要超过1000000行(1条用来查询Account,1000条用于Order,1000000条用于OrderItem),而创建的对象大约为2500万——如果你真敢这么做,等你的系统管理员收拾你吧。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值