ResultType和ResultMap的用法和区别

ResultType和ResultMap的用法和区别目录综述 ResultType 返回常见类型 类似于 int 或者 Integer 返回 Map 返回一个对象 ResultMap 基本使用 id 和 result 高级使用 Constructor 元素 AssociationC 综述 MyBatis 中在查询进行 select 映射的时候 返回类型可以用 resultType

目录

综述

ResultType

返回常见类型:(类似于int或者Integer)

返回Map

返回一个对象

ResultMap

基本使用

id和result

高级使用

Constructor元素

Association

Collection

discriminator


 


综述

ResultType

resultType可以直接返回给出的返回值类型,比如String、int、Map,等等,其中返回List也是将返回类型定义为Map,然后mybatis会自动将这些map放在一个List中,resultType还可以是一个对象,举例如下:

返回常见类型:(类似于int或者Integer)

  

返回Map

返回一个对象或者一个list(list里面是resultType的类型)

返回一个对象

对于SQL语句查询出的字段在相应的pojo中必须有和它相同的字段对应。

但是,如果列名没有精确匹配,你可以在列名上使用 select 字句的别名(一个 基本的 SQL 特性)来匹配标签。

 

ResultMap

基本使用

适合使用返回值是自定义实体类的情况

映射实体类的数据类型

id:resultMap的唯一标识

column: 库表的字段名

property: 实体类里的属性名

配置映射文件:

 
     
     
     
      
      
       
       
       
       
       
       
      
      
      
      
      
      
      
    

id和result

这是最基本的结果集映射。id 和result 将列映射到属性或简单的数据类型字段(String, int, double, Date等)。

这两者唯一不同的是,在比较对象实例时id 作为结果集的标识属性。这有助于提高总体性能,特别是应用缓存和嵌套结果映射的时候。

Id、result属性如下:

Attribute

Description

property

映射数据库列的字段或属性。如果JavaBean 的属性与给定的名称匹配,就会使用匹配的名字。否则,MyBatis 将搜索给定名称的字段。两种情况下您都可以使用逗点的属性形式。比如,您可以映射到“username”,也可以映射到“address.street.number”。

column

数据库的列名或者列标签别名。与传递给resultSet.getString(columnName)的参数名称相同。

javaType

完整java类名或别名(参考上面的内置别名列表)。如果映射到一个JavaBean,那MyBatis 通常会自行检测到。然而,如果映射到一个HashMap,那您应该明确指定javaType 来确保所需行为。

jdbcType

这张表下面支持的JDBC类型列表列出的JDBC类型。这个属性只在insert,update或delete 的时候针对允许空的列有用。JDBC 需要这项,但MyBatis 不需要。如果您直接编写JDBC代码,在允许为空值的情况下需要指定这个类型。

typeHandler

我们已经在文档中讨论过默认类型处理器。使用这个属性可以重写默认类型处理器。它的值可以是一个TypeHandler实现的完整类名,也可以是一个类型别名。

高级使用

MyBatis的创建基于这样一个思想:数据库并不是您想怎样就怎样的。虽然我们希望所有的数据库遵守第三范式或BCNF(修正的第三范式),但它们不是。如果有一个数据库能够完美映射到所有应用程序,也将是非常棒的,但也没有。结果集映射就是MyBatis为解决这些问题而提供的解决方案。

示例

 
     
     
      
       
      
      
      
       
       
       
       
       
       
      
      
       
       
       
       
        
       
       
        
       
       
        
       
      
    

resultMap

·constructor–实例化的时候通过构造器将结果集注入到类中

idArg,arg–注入构造器的结果集

·id–结果集ID,将结果集标记为ID,以方便全局调用

·result–注入一个字段或者javabean属性的结果

·association–复杂类型联合;许多查询结果合成这个类型

嵌套结果映射– associations能引用自身,或者从其它地方引用,

·collection–复杂类型集合

嵌套结果映射– collections能引用自身,或者从其它地方引用

·discriminator–使用一个结果值以决定使用哪个resultMap

case–基于不同值的结果映射

嵌套结果映射–case也能引用它自身, 所以也能包含这些同样的元素。它也可以从外部引用resultMap

注意:

public class A{ private B b1; private List  b2; } 在映射b1属性时用association标签, 映射b2时用collection标签,分别是一对一,一对多的关系 

Constructor元素

通常情况下, java实体类的属性都有get和set方法,但是在有的不变类中,没有get和set方法,只能在构造器中注入属性,这个时候就要constructor元素

 
     
      
      
      
    

当属性与DTO,或者与您自己的域模型一起工作的时候,许多场合要用到不变类。通常,包含引用,或者查找的数据很少或者数据不会改变的的表,适合映射到不变类中。构造器注入允许您在类实例化后给类设值,这不需要通过public方法。MyBatis同样也支持private属性和JavaBeans的私有属性达到这一点,但是一些用户可能更喜欢使用构造器注入。构造器元素可以做到这点。

public class User {    //...    public User(Integer id, String username, int age) {      //...   } //... }
 
    
          
          
          
      
     
 
    
          
          
          
      
    
 
     
      
      
      
    

其它的属性与规则与id、result元素的一样。

Attribute

Description

column

数据库的列名或者列标签别名。与传递给resultSet.getString(columnName)的参数名称相同。

javaType

完整java类名或别名(参考上面的内置别名列表)。如果映射到一个JavaBean,那MyBatis 通常会自行检测到。然而,如果映射到一个HashMap,那您应该明确指定javaType 来确保所需行为。

jdbcType

支持的JDBC类型列表中列出的JDBC类型。这个属性只在insert,update 或delete 的时候针对允许空的列有用。JDBC 需要这项,但MyBatis 不需要。如果您直接编写JDBC代码,在允许为空值的情况下需要指定这个类型。

typeHandler

我们已经在文档中讨论过默认类型处理器。使用这个属性可以重写默认类型处理器。它的值可以是一个TypeHandler实现的完整类名,也可以是一个类型别名。

 

Association

关联

 
    
        
        
      
    

·Nested Select:通过执行另一个返回预期复杂类型的映射SQL语句(即引用外部定义好的SQL语句块)。

·Nested Results:通过嵌套结果映射(nested result mappings)来处理联接结果集(joined results)的重复子集。

 

它不同于普通只有select和resultMap属性的结果映射。

Attribute

Description

property

映射数据库列的字段或属性。如果JavaBean 的属性与给定的名称匹配,就会使用匹配的名字。否则,MyBatis 将搜索给定名称的字段。两种情况下您都可以使用逗点的属性形式。比如,您可以映射到”username”,也可以映射到更复杂点的”address.street.number”。

column

数据库的列名或者列标签别名。与传递给resultSet.getString(columnName)的参数名称相同。

注意: 在处理组合键时,您可以使用column= “{prop1=col1,prop2=col2}”这样的语法,设置多个列名传入到嵌套查询语句。这就会把prop1和prop2设置到目标嵌套选择语句的参数对象中。

javaType

完整java类名或别名(参考上面的内置别名列表)。如果映射到一个JavaBean,那MyBatis 通常会自行检测到。然而,如果映射到一个HashMap,那您应该明确指定javaType 来确保所需行为。

jdbcType

支持的JDBC类型列表中列出的JDBC类型。这个属性只在insert,update 或delete 的时候针对允许空的列有用。JDBC 需要这项,但MyBatis 不需要。如果您直接编写JDBC代码,在允许为空值的情况下需要指定这个类型。

typeHandler

我们已经在文档中讨论过默认类型处理器。使用这个属性可以重写默认类型处理器。它的值可以是一个TypeHandler实现的完整类名,也可以是一个类型别名。

联合嵌套选择(Nested Select for Association)

select

通过这个属性,通过ID引用另一个加载复杂类型的映射语句。从指定列属性中返回的值,将作为参数设置给目标select 语句。表格下方将有一个例子。注意:在处理组合键时,您可以使用column=”{prop1=col1,prop2=col2}”这样的语法,设置多个列名传入到嵌套语句。这就会把prop1和prop2设置到目标嵌套语句的参数对象中。

 
    
         
     
                 
      
           SELECT * FROM BLOG WHERE ID = #{id}          
       
            SELECT * FROM AUTHOR WHERE ID = #{id}      
            
        
       
      
    

我们使用两个select语句:一个用来加载Blog,另一个用来加载Author。Blog的resultMap 描述了使用“selectAuthor”语句来加载author的属性。

如果列名和属性名称相匹配的话,所有匹配的属性都会自动加载。

上面的例子,首先执行查出的数据都会自动赋值给”blogResult”的与列名匹配的属性,这时blog_id,title等就被赋值了。同时“blogResult”还有一个关联属性”Author”,执行嵌套查询select=”selectAuthor”后,Author对象的属性id,username,password,email,bio也被赋于数据库匹配的值。

Blog { blog_id; title; Author author { id; username; password; email; bio; } }

虽然这个方法简单,但是对于大数据集或列表查询,就不尽如人意了。这个问题被称为“N+1 选择问题”(N+1 Selects Problem)。概括地说,N+1选择问题是这样产生的:

·您执行单条SQL语句去获取一个列表的记录( “+1”)。

·对列表中的每一条记录,再执行一个联合select 语句来加载每条记录更加详细的信息(“N”)。

这个问题会导致成千上万的SQL语句的执行,因此并非总是可取的。

上面的例子,MyBatis可以使用延迟加载这些查询,因此这些查询立马可节省开销。然而,如果您加载一个列表后立即迭代访问嵌套的数据,这将会调用所有的延迟加载,因此性能会变得非常糟糕。

鉴于此,这有另外一种方式。

联合嵌套结果集(Nested Results for Association) 

resultMap

一个可以映射联合嵌套结果集到一个适合的对象视图上的ResultMap 。这是一个替代的方式去调用另一个select 语句。它允许您去联合多个表到一个结果集里。这样的结果集可能包括冗余的、重复的需要分解和正确映射到一个嵌套对象视图的数据组。简言之,MyBatis 让您把结果映射‘链接’到一起,用来处理嵌套结果。举个例子会更好理解,例子在表格下方。

您已经在上面看到了一个非常复杂的嵌套联合的例子,接下的演示的例子会更简单一些。我们把Blog和Author表联接起来查询,而不是执行分开的查询语句:

 
    
         select   B.id as blog_id,   B.title as blog_title,   B.author_id as blog_author_id,   A.id as author_id,   A.username as author_username,   A.password as author_password,   A.email as author_email,   A.bio as author_bio   from Blog B left outer join Author A on B.author_id = A.id   where B.id = #{id}      
    
 
    
         
        
        
     
                 
      
           
          
          
          
          
             
       
      
    

在上面的例子中,您会看到Blog的作者(“author”)联合一个“authorResult”结果映射来加载Author实例。

重点提示:id元素在嵌套结果映射中扮演了非常重要的角色,您应该总是指定一个或多个属性来唯一标识这个结果集。事实上,如果您没有那样做,MyBatis也会工作,但是会导致严重性能开销。选择尽量少的属性来唯一标识结果,而使用主键是最明显的选择(即使是复合主键)。

上面的例子使用一个扩展的resultMap 元素来联合映射。这可使Author结果映射可重复使用。然后,如果您不需要重用它,您可以直接嵌套这个联合结果映射。下面例子就是使用这样的方式: 

 
    
         
        
        
     
          
         
         
         
         
              
      
    

在上面的例子中您已经看到如果处理“一对一”(“has one”)类型的联合查询。

Collection

 
    
         
        
        
          
    

collection元素的作用差不多和association元素的作用一样。事实上,它们非常相似,以至于再对相似点进行描述会显得冗余,因此我们只关注它们的不同点。

继续我们上面的例子,一个Blog只有一个Author。但一个Blog有许多帖子(文章)。在Blog类中,会像下面这样定义相应属性: 

private List posts;

映射一个嵌套结果集到一个列表,我们使用collection元素。就像association 元素那样,我们使用嵌套查询,或者从连接中嵌套结果集。 

集合嵌套选择(Nested Select for Collection)

首先我们使用嵌套选择来加载Blog的文章。 

 
    
         
     
                 
      
           SELECT * FROM BLOG WHERE ID = #{id}          
       
            SELECT * FROM POST WHERE BLOG_ID = #{id}      
        
       
      
    

一看上去这有许多东西需要注意,但大部分看起与我们在association元素中学过的相似。首先,您会注意到我们使用了collection元素,然后会注意到一个新的属性“ofType”。这个元素是用来区别JavaBean属性(或者字段)类型和集合所包括的类型。因此您会读到下面这段代码。

 
    

理解为:“一个名为posts,类型为Post的ArrayList集合(A collection of posts in an ArrayList of type Post)” 。

javaType属性不是必须的,通常MyBatis 会自动识别,所以您通常可以简略地写成:

 
    

 

集合的嵌套结果集(Nested Results for Collection)

这时候,您可能已经猜出嵌套结果集是怎样工作的了,因为它与association非常相似,只不过多了一个属性“ofType”

 
    
         select   B.id as blog_id,   B.title as blog_title,   B.author_id as blog_author_id,   P.id as post_id,   P.subject as post_subject,   P.body as post_body,   from Blog B   left outer join Post P on B.id = P.blog_id   where B.id = #{id}   
    
 
    
         
        
        
     
          
         
         
               
      
    

再次强调一下,id 元素是非常重要的。如果您忘了或者不知道id 元素的作用,请先读一下上面association一节。

如果希望结果映射有更好的可重用性,您可以使用下面的方式:

 
    
         
        
        
               
     
          
         
         
            
      
    

在您的映射中没有深度、宽度、联合和集合数目的限制。但应该谨记,在进行映射的时候也要考虑性能的因素。应用程序的单元测试和性能测试帮助您发现最好的方式可能要花很长时间。但幸运的是,MyBatis允许您以后可以修改您的想法,这时只需要修改少量代码就行了。

discriminator

 
    
        
      
    
 
    
        
        
        
        
        
        
        
     
           
           
           
           
         
      
    
 
    
        
      
    
 
    
        
      
    
 
    
        
        
        
        
        
        
        
     
           
      
              
            
           
      
              
              
            
           
      
              
            
           
      
              
            
         
      
    
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227987.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午8:03
下一篇 2026年3月16日 下午8:03


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号