Mybatis中resultMap


2013-12-26 14:50:34|  分类: 默认分类|举报|字号 订阅

MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接
表示返回类型的,而resultMap则是对外部ResultMap的引用,但是resultType跟resultMap不能同时存在。

1.resultType

 

在MyBatis进行查询映射的时候,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,
值则是其对应的值。当提供的返回类型属性是resultType的时候,MyBatis会将Map里面的键值对取出赋给
resultType所指定的对象对应的属性。所以其实MyBatis的每一个查询映射的返回类型都是ResultMap,
只是当我们提供的返回类型属性是resultType的时候,MyBatis对自动的给我们把对应的值赋给resultType
所指定对象的属性,而当我们提供的返回类型是resultMap的时候,因为Map不能很好表示领域模型,
我们就需要自己再进一步的把它转化为对应的对象,这常常在复杂查询中很有作用。

 

这里要强调的是,Mybatis是对返回的结果的每一行做映射的。所以,下面的语句返回的是Integer,而不是List

 

 

Xml代码  复制代码  收藏代码
  1.   
  2.         SELECT id FROM USER  
  3.   

 

返回一个int

 

Xml代码  复制代码  收藏代码
  1.   
  2.         SELECT count(*) FROM USER  
  3.   

 

返回map

Xml代码  复制代码  收藏代码
  1.   
  2.     select id, username, hashedPassword  
  3.     from some_table  
  4.     where id = #{id}  
  5.   

 

这样一个语句简单作用于所有列被自动映射到HashMap的键上,这由resultType属性指定。这在很多情况下是有用的,但是HashMap不能很好描述一个领域模型。那样你的应用程序将会使用JavaBeans或POJOs(Plain Old Java Objects,普通Java对象)来作为领域模型

返回javaBEAN 对象

 

Xml代码  复制代码  收藏代码
  1.   
  2.         SELECT * FROM USER  
  3.    

 

要记住类型别名是你的伙伴。使用它们你可以不用输入类的全路径。

 

Xml代码  复制代码  收藏代码
  1.   

 这些情况下,MyBatis会在幕后自动创建一个ResultMap,基于属性名来映射列到JavaBean的属性上

 

2.resultMap

 

MyBatis会自动创建一个ResultMap对象,然后基于查找出来的属性名进行键值对封装,然后再看到返回类型是Blog对象,再从ResultMap中取出与Blog对象对应的键值对进行赋值。

当返回类型直接是一个ResultMap的时候也是非常有用的,这主要用在进行复杂联合查询上,因为进行简单查询是没有什么必要的。

 

简单resultMap配置 

 

Xml代码  复制代码  收藏代码
  1.     
  2.         
  3.         
  4.         
  5.         
  6.    
  7.    
  8.     
  9.       select * from t_blog where id = #{id}    
  10.   

 

结果集的列比resultMap多会报错么?
不会,只映射resultMap中有的列。

 

结果集的列比resultMap少会报错么?
不会,只映射结果集中有的列。

 

高级结果映射

 

Xml代码  复制代码  收藏代码
  1.   
  2.       
  3.           
  4.       
  5.       
  6.       
  7.           
  8.           
  9.           
  10.           
  11.           
  12.           
  13.       
  14.       
  15.           
  16.           
  17.           
  18.           
  19.               
  20.           
  21.           
  22.               
  23.           
  24.           
  25.               
  26.           
  27.       
  28.   

 

 

resultMap
      constructor – 类在实例化时,用来注入结果到构造方法中
           idArg – ID参数;标记结果作为ID可以帮助提高整体效能
           arg – 注入到构造方法的一个普通结果
      id – 一个ID结果;标记结果作为ID可以帮助提高整体效能
      result – 注入到字段或JavaBean属性的普通结果
     association – 一个复杂的类型关联;许多结果将包成这种类型
           嵌入结果映射 – 结果映射自身的关联,或者参考一个
     collection – 复杂类型的集
           嵌入结果映射 – 结果映射自身的集,或者参考一个
    discriminator – 使用结果值来决定使用哪个结果映射
         case – 基于某些值的结果映射
               嵌入结果映射 – 这种情形结果也映射它本身,因此可以包含很多相同的元素,或者它可以参照一个外部的结果映射。

 

 

id 和result
   
id和result都映射一个单独列的值到简单数据类型

 

这两者之间的唯一不同是id表示的结果将是当比较对象实例时用到的标识属性。这帮助来改进整体表现,特别是缓存和嵌入结果映射(也就是联合映射)。

 

它们共有的属性如下:

 

property

 

映射到列结果的字段或属性。如果匹配的是存在的,和给定名称相同的JavaBeans的属性,那么就会使用。否则MyBatis将会寻找给定名称的字段。这两种情形你可以使用通常点式的复杂属性导航。比如,你可以这样映射一些东西:“username”,或者映射到一些复杂的东西:“address.street.number”。

 

column

 

从数据库中得到的列名,或者是列名的重命名标签。这也是通常和会传递给resultSet.getString(columnName)方法参数中相同的字符串。

 

javaType

 

一个Java类的完全限定名,或一个类型别名(参加上面内建类型别名的列表)。如果你映射到一个JavaBean,MyBatis通常可以断定类型。然而,如果你映射到的是HashMap,那么你应该明确地指定javaType来保证所需的行为。

 

jdbcType

 

在这个表格之后的所支持的JDBC类型列表中的类型。JDBC类型是仅仅需要对插入,更新和删除操作可能为空的列进行处理。这是JDBC的需要,而不是MyBatis的。如果你直接使用JDBC编程,你需要指定这个类型-但仅仅对可能为空的值。

 

typeHandler

 

我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默认的类型处理器。这个属性值是类的完全限定名或者是一个类型处理器的实现,或者是类型别名。


constructor

 

。构造方法注入允许你在初始化时为类设置属性的值,而不用暴露出公有方法。MyBatis也支持私有属性和私有JavaBeans属性来达到这个目的,但是一些人更青睐构造方法注入。

为了向这个构造方法中注入结果,MyBatis需要通过它的参数的类型来标识构造方法。Java没有自查(反射)参数名的方法。所以当创建一个构造方法元素时,保证参数是按顺序排列的,而且数据类型也是确定的。

 

association

 

association关联元素处理“有一个”类型的关系,即一对一关联。它有两种关联方式

 

嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型。

 

嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集。

 

嵌套查询

 

Xml代码  复制代码  收藏代码
  1.   
  2.       
  3.       
  4.       
  5.       
  6.       
  7.   
  8.   
  9.      
  10.     select * from User where id =#{id}     
  11.    
  12.   
  13.      
  14.     select * from Role where id =#{id}     
  15.    

 

这里有两个查询,一个查询加载User,一个查询加载Role.
这里select为另外一个映射语句的ID,可以加载这个属性映射需要的复杂类型。获取的在列属性中指定的列的值将被传递给目标select语句作为参数。

 

注意:
而select 为selectRole的SQL输入参数可以随便给名称,只要是输入参数与压入进去的值类型相同就行了,可以写成:

 

Xml代码  复制代码  收藏代码
  1. select * from Role where id = #{sfffs}   

 

不管输入参数名称是什么,mybatis最终会执行:
效果为:

 

Sql代码  复制代码  收藏代码
  1. select * from role where id =resultSet.getLong("Role_id");  

 

注意:要保证第二个查询查出来的结果只有一条记录。

 

要处理复合主键,你可以指定多个列名通过column="{prop1=col1,prop2=col2}"这种语法来传递给嵌套查询语句。这会引起prop1和prop2以参数对象形式来设置给目标嵌套查询语句。

Xml代码  复制代码  收藏代码
  1.   
  2.       
  3.       
  4.       
  5.       
  6.       
  7.   
  8.   
  9.      
  10.     select * from Role where id =#{id} and name= #{name}     
  11.   

  

这种方式很简单,但是对于大型数据集合和列表将不会表现很好。问题就是我们熟知的“N+1查询问题”。概括地讲,N+1查询问题可以是这样引起的:


   你执行了一个单独的SQL语句来获取结果列表(就是“+1”)。
   对返回的每条记录,你执行了一个查询语句来为每个加载细节(就是“N”)。


这个问题会导致成百上千的SQL语句被执行。这通常不是期望的。


比如一个查询用户列表的SQL,假如有2000个用户,那么就是一个查询用户的SQL和2000个查询角色的SQL,一共有2001个SQL被运行。


MyBatis能延迟加载这样的查询就是一个好处,因此你可以分散这些语句同时运行的消耗。然而,如果你加载一个列表,之后迅速迭代来访问嵌套的数据,你会调用所有的延迟加载,这样的行为可能是很糟糕的。

 

所以还有另外一种方法。


关联的嵌套结果

 

嵌套结果

 

Xml代码  复制代码  收藏代码
  1.   
  2.       
  3.       
  4.       
  5.       
  6.       
  7.           
  8.           
  9.       
  10.   
  11.   
  12.   
  13.       
  14.       
  15.   

 

 

也可以这样配置

 

Xml代码  复制代码  收藏代码
  1.   
  2.       
  3.       
  4.       
  5.       
  6.       
  7.   
  8.   
  9.   
  10.       
  11.       
  12.   

 

 resultMap这是结果映射的ID,可以映射关联的嵌套结果到一个合适的对象图中。这是一种替代方法来调用另外一个查询语句。这允许你联合多个表来合成到一个单独的结果集。这样的结果集可能包含重复,数据的重复组需要被分解,合理映射到一个嵌套的对象图。为了使它变得容易,MyBatis让你“链接”结果映射,来处理嵌套结果。一个例子会很容易来仿照,这个表格后面也有一个示例。

 

注意这个联合查询,以及采取保护来确保所有结果被唯一而且清晰的名字来重命名。

 

columnPrefix 属性

 

Xml代码  复制代码  收藏代码
  1.   
  2.           
  3.           
  4.   

 

非常重要:在嵌套据诶过映射中id元素扮演了非常重要的角色。应应该通常指定一个或多个属性,它们可以用来唯一标识结果。实际上就是如果你离开她了,但是有一个严重的性能问题时MyBatis仍然可以工作。选择的属性越少越好,它们可以唯一地标识结果。主键就是一个显而易见的选择(尽管是联合主键)。

 

上面你已经看到了如何处理“有一个”类型关联。但是“有很多个”是怎样的?下面这个部分就是来讨论这个主题的。

 

collection

 

collection关联元素处理一对多关联。

 

Xml代码  复制代码  收藏代码
  1.   
  2.       
  3.       
  4.       
  5.       
  6.   
  7.   
  8.   
  9.      
  10.     select * from uer where id =#{id}   
  11.    

 

同样,可以这样配置

 

Xml代码  复制代码  收藏代码
  1.   
  2.       
  3.       
  4.       
  5.       
  6.           
  7.           
  8.       
  9.   
  10.   
  11.       
  12.       
  13.   

你可能感兴趣的:(Mybatis)