zoukankan      html  css  js  c++  java
  • iBatis.Net系列(六) ResultMap

    我们将来讨论一下在 iBatis 中非常重要的一个内容,在我个人看来,能否真正用好 iBatis 的一个关键,这就是 ResultMap 。字面上理解,它就是结果集的映射,就是将返回的记录逐个字段的映射赋值给对象的属性上。其实如果没有特殊需求的话我们完全可以使用 ResultClass 来代替它,因为如果字段与属性一模一样的话,查询出来数据集会自动匹配到 ResultClass 指定的类的实例对象,如果字段名不在属性中的话,那这个字段将不会被返回的实例体类对象接受,相当于没有查询出这个字段一样的。

    每个 ResultMap 都有一个自己的 ID ,如果你在 sqlmap.config 中没有配置使用命名空间的话,那么这个 ResulteMap ID 是全局(这点在所有的 iBatis 配置元素都是一样的), ResultMap 一个重要的属性的是 class, 它将决定这个 ResultMap 对应的实例的类,换句话讲,它的作用是指出结果集要映射的数据类型。在 extends 属性中可以设置它将要继承的 ResultMap ,如果给他指定的了值,那么它将会从 super Resultmap 继承所的映射配置字段。定义如下:

    < resultMaps >

             < resultMap id = "DemoResultMap " class = "Hashtable ">

                 

             </ resultMap >

    </ resultMaps >

    如果你有正确配置了iBatisXSD 架构文件的话,那么这时候就会提示resultMap 的定义是不完全的。 没错,接下来就是要定义 Result 元素。每一个 result 元素都是定义一个字段与数据类属性对应的映射。在每一个 result 元素有比较多的属性参数,其中 property column 是必须的,其它的参数属性都是可选的。所以我们在每一个 resultMap 中必须定义超过一个以上的 result 定义。通常以下的配置就可以完成基本的配置了。

    < resultMaps >

             < resultMap id = "DemoResultMap " class = "Hashtable ">

                  < result property = "id " column = "id "/>

             </ resultMap >

    </ resultMaps >

         但如果你需要更多的要求的话,result map 仍然能够最大限度的满足你。columnIndex 属性提供了我们将数据集的第几个下标字段映射到指定的数据对象属性的方案,但是这种方式应该尽量的少用,你会发现这对我们以后的维护和可读性会产生很大的副作用。dbType 属性明确指出这个字段对应的数据库的类型,大多数情况我很少会用到。type 属性则明确指出这个字段将对应的数据对象属性的数据类型,通常如果你想保证类型安全的话,设置这个属性是很必要的。resultMapping 属性则稍微复杂一些,它是用在一种场景下,如果一个数据类的属性本身不是基元数据类型,而是一个复杂数据类型的话,那我们就不可能很简单地给它一个简单的result 元素就了事了,还必须给他一个完整的resultMap 。而resultMapping 属性就是为了完成这个功能而存在的。它的属性值是一个已存在的resultMapIDnullValue 属性就没什么好讲的了,它是给出当这个字段的值为null 的时候,它的默认值是多少。select 属性同resultMapping 一样比较复杂一样,先说一下它的属性值必须是一个返回数据集合的查询语句的ID ,能配置这个属性的数据类属性可以是一个基元类型,复合类型,也可以是一个包括多条数据的集合类型,这些类型都行,没有问题的。它的一处重要的存在意义就在于描述不同表之间的关系问题,通过本次的查询,你想不通过join 的手段从另一个表查询相关字段的时候,你就可以使用select 属性。如下:

    < resultMaps >

             < resultMap id = "DemoResultMap " class = "Hashtable ">

                  < result property = "id " column = "id "/>

                  < result property = "Children " column = "id " select = "SELECT_Children "/>

             </ resultMap >

         </ resultMaps >

         < statements >

             < select id = "SELECT_Children " resultClass = "ChildrenObject ">

                  SELECT * FROM Children WHERE ParentID = #id#

             </ select >

         </ statements >

    这样就可以做到不用通过编程的方式来表示不同表的关联关系和数据读取问题。但是这样有可能存在一种问题,如果你每次都要读取数据的时候,你会发现你会产生更多次的与数据库交互的情况,并且即使你不是每次都需要这数据,那会不会造成数据读取的浪费呢?接下来的lazyLoad 属性就为我们提供了第二种问题的解决方案了,那就是数据的延迟加载,没错,延迟加载可以大大改善数据访问的性能,它只是要需的时候才去读取这些数据,对于主从表关系的时候,这样的方式可能是最好的解决方式了。

        OK ,关于ResultMap 的介绍就先到此为止,接下来我要记录一下,我在使用过程中遇到的一些问题:

        一.在使用ResultMap 的时候,你要特别注意,如果你在ResultMap 中给出的配置字段,但是你返回的数据集的时候却没有返回这个字段,那程序将出抛出异常。但是相反的,如果你返回了一些字段,却没有在ResultMap 给出配置定义的话,那么那些字段将不会被处理而不会给你任何的提示,相当没有查询出这些字段。你要特别注意这个问题。

           二.如果没有特别需求的情况,我建议还是把数据类的属性设计成与数据库字段字一样的比较,这样如果一般情况下我们都可以不用写这个 ResultMap ,事实上如果没有这样的特殊要求,那么去写这个 ResultMap 仍然是一件非常耗时,并且容易出错的一份差事。

           三.在使用 lazyLoad 的时候要特别注意,不是什么类型的数据都可以 lazyLoad 的,只有是实现的 IList 的接口的类型,并且数据类的属性定义为 IList 类型的字段才能被 lazyLoad 。(关于是否只有 IList 类型的属性才能被 lazyLoad 的问题还需要探讨一下,因为就我使用的经验只有这种类型才可以,甚至是 Generic 版的 IList 都不支持)。而且你在使用它的时候,还不能把这个 IList 类型的属性转换成你真正的数据类型。因为在运行时,这个属性会被包装成一个动态的类型,这个动态类型仍然实现了 IList 接口,就是因为这个动态类型才扩展了我们可以 lazyLoad 的功能。这时候在程序中使用的是运行时的动态类型所以你没办法进行强类型转换。

           问题暂时没有想到更多了,如果以后还有关于 resultMap 的问题,我都会更新上来,也希望大家一起来指正我的一些错误和不足,一起完善。不要让我的一些错误的实践误导了初学者,谢谢。

    阿不 http://hjf1223.cnblogs.com
  • 相关阅读:
    好用的Win7下硬盘分区软件:Acronis Disk Director Suite
    SQL Server 相关create操作语句
    我也有博客了
    N层构架如何实现
    SQL相关增删改查语句
    1.MVC的工作流程
    回顾去年以来读过的书
    [Architecture]Facebook Chat
    [Tips]解决make_sock: could not bind to address 0.0.0.0:XXXX
    Emacs中的按键组合
  • 原文地址:https://www.cnblogs.com/cpcpc/p/2123138.html
Copyright © 2011-2022 走看看