myBatis中的语句映射几种特别方式
来源:互联网 发布:图像增强算法有哪些 编辑:程序博客网 时间:2024/05/17 16:03
对于myBatis中的高级映射通常会使用resultMap参数,而非使用resultType参数,虽然对于大多数的查询来说resultType会更常用,其实这两种方式都是比较好使用的,只通常来说,当配置为resultType参数,所做的映射查询通常会简单一些,而使用resultMap参数要相对复杂一些,不如果不是太复杂使用resultMap没有太大的意义,因为它需要多配置一个resutMap映射结点对象,但有时你会发现,在查询时90%字段来源于一个表,而只有相别字段来源于另一个表,此时如果使用resultMap其实就有些得不偿失,但有些开发人却不知道怎样使用较简单的方法来处理它,其实很很简单,具体可以查看下面的配置:
<select id="getLogs" parameterType="CoreLog" resultType="CoreLog">select<include refid="fieldAsProperty" />,bb.cract_Name AS "strMap.cractName"from core_log aa left join core_account bb on aa.crlog_cract_uuid = bb.cract_uuid<where><include refid="conditionA" /></where>order by crlog_cdate desc</select>
上面其实就是使用比较简单的方法将数据库列映射到了bean的一个属性strMap.cractName上面,这是一个带有链式的语法,如果采用resultMap写法可能就会比较麻烦,例如:
<resultMap type="CoreLog" id="fieldMapperEX" extends="fieldMapper"><result property="strMap.cractName" column="cractName"/></resultMap><select id="getLogs" parameterType="CoreLog" resultMap="fieldMapperEX">select<include refid="fieldAsProperty" />,bb.cract_Name AS cractNamefrom core_log aa left join core_account bb on aa.crlog_cract_uuid = bb.cract_uuid<where><include refid="conditionA" /></where>order by crlog_cdate desc</select>
这里需要修正说明一下:对于上面的第一种写法是不完全正确的,这可能是当前myBatis3.0.5不够完善的地方这里需要说明下这两种写法的原理,其实终这两种写法最终的落脚点在第二种方法,第一种方法只所不需要这种配置是因为它通过指定resultType与列名称进行了一种反射不区分大小写的适配,但这是种适配现在还有不完善的地方,主要体现在链式语法中间含有一些非javaBean类型(例如上面的Map类型),则框架进行推测就会出错,具体逻辑可以查看以下源代码.
protected boolean applyAutomaticMappings(ResultSet rs, List<String> unmappedColumnNames, MetaObject metaObject) throws SQLException { boolean foundValues = false; for (String columnName : unmappedColumnNames) { final String property = metaObject.findProperty(columnName); if (property != null) { final Class propertyType = metaObject.getSetterType(property); if (typeHandlerRegistry.hasTypeHandler(propertyType)) { final TypeHandler typeHandler = typeHandlerRegistry.getTypeHandler(propertyType); final Object value = typeHandler.getResult(rs, columnName); if (value != null) { metaObject.setValue(property, value); foundValues = true; } } } } return foundValues; }
public String findProperty(String propName) { return objectWrapper.findProperty(propName); }
public String findProperty(String name) { return metaClass.findProperty(name); }
public String findProperty(String name) { StringBuilder prop = buildProperty(name, new StringBuilder()); return prop.length() > 0 ? prop.toString() : null; }
private StringBuilder buildProperty(String name, StringBuilder builder) { PropertyTokenizer prop = new PropertyTokenizer(name); if (prop.hasNext()) { String propertyName = reflector.findPropertyName(prop.getName()); if (propertyName != null) { builder.append(propertyName); builder.append("."); MetaClass metaProp = metaClassForProperty(propertyName); metaProp.buildProperty(prop.getChildren(), builder); } } else { String propertyName = reflector.findPropertyName(name); if (propertyName != null) { builder.append(propertyName); } } return builder; }
public String findPropertyName(String name) {return caseInsensitivePropertyMap.get(name.toUpperCase(Locale.ENGLISH));}
通过源代码的追踪你会发现缺陷出在org.apache.ibatis.reflection.Reflector#findPropertyName,它只考虑了标准的javaBean反射,对于Map类型的数据没有进行考虑,当然它是指在链式语法的中间存在Map型数据才会不能正确的返回属性的名称,或或许在将来的某个版本中可以支持类似Map类型数据的链式语法.
但是对于javaBean成员字段属性则不存在这样的问题,例如:
<select id="getMultiOrgsByUsr" resultType="CoreAccount" parameterType="CoreAccount">select cc.cract_name as cractName, cc.cract_Unid as cractUnid,cc.cract_Uuid as cractUuid,cc.cract_crorg_uuid as cractCrorgUuid,aa.cramo_unid as "coreAccountOrganiz.cramoUnid",bb.crorg_full_name as "coreOrganization.crorgFullName",bb.crorg_uuid as "coreOrganization.crorgUuid"from core_account_organiz aa left join core_organization bb on aa.cramo_crorg_uuid = bb.crorg_uuidleft join core_account cc on aa.cramo_cract_uuid = cc.cract_uuidwhere aa.cramo_cract_uuid = #{cractUuid}</select>
上面的coreAccountOrganiz与coreOrganization都属于CoreAccount的成员字段,将其中的几个数据库列字段映射到成员中的某几个字段段上,从上面的分析可以看出对从一张表查询所有字段,而从另外的一张表中查询少量字段可以优先使用resultType参数是一种最适合的方法,对于resultMap配置,通常对于单表映射开发人员都会使用代码生成工具生成,对于这种情况,如果希望映射出类似于Hibernate的效果,如果还使用resultType参数就会有些不好做,需要写很多SQL,如果使用resultMap参数就可以共享单表的映射定义,具体参考下面的配置:
这上CoreAccount的映射配置:
<resultMap id="fieldMapper" type="CoreAccount"><id property="cractUnid" column="cractUnid" /><!--标识UNID--><result property="cractUuid" column="cractUuid" /><!--标识UUID--><result property="cractLevelCode" column="cractLevelCode" /><!--层级编码--><result property="cractCrorgUuid" column="cractCrorgUuid" /><!--默认机构--><result property="cractIdNumber" column="cractIdNumber" /><!--身份证号--><result property="cractMobile" column="cractMobile" /><!--手机号码--><result property="cractJobNumber" column="cractJobNumber" /><!--职位代码--><result property="cractLevel" column="cractLevel" /><!--帐户级别--><result property="xxxxx" column="xxxx" /><!--帐户代码--></resultMap>
下面是CoreAccountOrganiz映射配置:
<resultMap id="fieldMapper" type="CoreAccountOrganiz"><id property="cramoUnid" column="cramoUnid" /><!--标识UNID--><result property="cramoCractUuid" column="cramoCractUuid" /><!--帐户UUID--><result property="cramoCrorgUuid" column="cramoCrorgUuid" /><!--机构部门UUID--><result property="cramoOrd" column="cramoOrd" /><!--排序号--><result property="cramoExtCrorgUuid" column="cramoExtCrorgUuid" /><!--机构UUID--><result property="cramoExt1" column="cramoExt1" /><!--扩展字段1--><result property="cramoExt2" column="cramoExt2" /><!--扩展字段2--></resultMap>
如果这两张表要进行关联查询映射,并且希望在CoreAccount对象中获取一个完整的CoreAccountOrganiz成员对象,则可以使用下面的方式:
<resultMap type="CoreAccount" id="fieldMapperEX" extends="fieldMapper"><association property="coreOrganization" resultMap="com.risen.core.dao.mapper.ICoreOrganizationMapper.fieldMapper" /><association property="coreAccountOrganiz" resultMap="com.risen.core.dao.mapper.ICoreAccountOrganizMapper.fieldMapper" /></resultMap>
这上面是映射两个成员对象,上面只是列举了一个,此时你就可以使用
<select id="getAccountByOrg" parameterType="CoreAccount" resultMap="fieldMapperEX">select <include refid="fieldAsProperty" />,<include refid="com.risen.core.dao.mapper.ICoreOrganizationMapper.fieldAsProperty" />,<include refid="com.risen.core.dao.mapper.ICoreAccountOrganizMapper.fieldAsProperty" />from core_account_organiz aajoin core_account bb on aa.cramo_cract_uuid = bb.cract_uuidjoin core_organization cc on bb.cract_crorg_uuid = cc.crorg_uuidwhere aa.cramo_crorg_uuid = #{cractCrorgUuid} and bb.cract_status != 2<if test="cractLevel != null" >and cract_level=#{cractLevel}</if>order by aa.cramo_ord</select>
来进行映射查询,而这里使用的是resultMap查询,此如果你需要映射字段就不应该在语句中来完成,而应该在fieldMapperEX对象中去定义,例如先前使用bb.cract_Name AS "strMap.cractName"这种语法基本是不起作用的因为在fieldMapperEX对象并没有定义strMap.cractName这样的字段映射,如果此时你还希望进行个别字段的映射还是需要在fieldMapperEX对象定义:strMap.cractName的映射,例如:
<resultMap type="CoreAccount" id="fieldMapperEX" extends="fieldMapper">
<result property="strMap.cractName" column="xxxxxxx" /><association property="coreOrganization" resultMap="com.risen.core.dao.mapper.ICoreOrganizationMapper.fieldMapper" /><association property="coreAccountOrganiz" resultMap="com.risen.core.dao.mapper.ICoreAccountOrganizMapper.fieldMapper" /></resultMap>
其实从这里对比着看你会发现result标签与association标签之间的其实差不多,只是association定义属类似于定义了一个前缀而已,上面也可以将strMap对象映射到另一个resultMap对象而在另一个resultMap对象不去映射字段:
<resultMap type="CoreLog" id="fieldMapperEX" extends="fieldMapper"><result property="cractName" column="cractName"/></resultMap>
此时你的strMap前缀就可以被取消掉了
- myBatis中的语句映射几种特别方式
- mybatis 构建SqlSessionFactory的几种方式 以及调用sql映射语句的几种方式
- MyBatis 映射SQL的几种方式
- MyBatis中的几种注解映射
- hibernate中的几种映射方式
- Selenium中的几种等待方式,需特别注意implicitlyWait的用法
- Selenium中的几种等待方式,需特别注意implicitlyWait的
- Selenium中的几种等待方式,需特别注意implicitlyWait的用法
- Selenium中的几种等待方式,需特别注意implicitlyWait的用法
- Selenium中的几种等待方式,需特别注意implicitlyWait的用法
- Selenium中的几种等待方式,需特别注意implicitlyWait的用法
- Selenium中的几种等待方式,需特别注意implicitlyWait的用法
- Selenium中的几种等待方式,需特别注意implicitlyWait的
- Selenium中的几种等待方式,需特别注意implicitlyWait的用法
- MyBatis mapper.xml配置一对一关系映射的几种方式整理
- hibernate中的几种映射
- MyBatis映射语句
- Mybatis SQL语句的两种映射方式 mapper的xml配置和接口两种方式
- c++:什么是深拷贝什么是浅拷贝!
- mysql查看所有存储过程
- 中介者模式(Mediator) [非原创--该篇文章大部分内容来自Yan YAN's Tech Space,底部附 C++实现]
- [UvaOJ - Getting Started] 10055 - Hashmat the Brave Warrior
- shell中的if语法
- myBatis中的语句映射几种特别方式
- 地址
- 如何去掉linux源文件里面的^M符号简单方法
- iOS: 设置ui background image
- [转] 如何复制百度文库中的文章。。。这个必须留一份。。。
- Java编程之URI
- 并不是所以人都喜欢你
- 上海移动EMPP协议控件(OCX)
- magento的Cannot initialize the indexer process解决方法