MyBatis 返回结果

自动映射

MyBatis 会获取结果中返回的列名并在 Java 类中查找相同名字的属性(忽略大小写)。 这意味着如果发现了数据库中的 ID 列和Java类中的 id 属性,MyBatis 会将列 ID 的值赋给 id 属性。

通常数据库列使用大写字母组成的单词命名,单词间用下划线分隔;而 Java 属性一般遵循驼峰命名法约定。为了在这两种命名方式之间启用自动映射,需要将mapUnderscoreToCamelCase 设置为 true。

<settings>
    <!--开启自动驼峰命名规则映射, 如果数据库字段为user_email, MyBatis会自动将其映射到Javabean中的userEmail属性-->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

resultType

通过resultType设置返回结果类型,基本数据类型与POJO类似,下面只演示POJO。

返回单个或者多个

  1. 通过username查询单个用户

接口定义如下

public User getUserByUserName(String userName);

接口对应的 Mapper.xml 定义如下所示

<select id="getUserByUserName"
        parameterType="String"
        resultType="com.example.mybatis.entity.User">
    select
    id, username, user_email userEmail, user_city userCity, age
    from user
    where username = #{username}
</select>
  1. 通过username查询多个用户

接口定义如下

public List<User> getUserListByUserName(String userName);

接口对应的 Mapper.xml 定义如下所示

<select id="getUserListByUserName"
        parameterType="String"
        resultType="com.example.mybatis.entity.User">
    select
    id, username, user_email userEmail, user_city userCity, age
    from user
    where username = #{username}
</select>

有时候需要将返回的List封装在一个Map里面,并使用实体类的某个字段作为Map的key

接口定义如下

@MapKey("id")
public Map<String, User> getUserListByUserName(String userName);

接口对应的 Mapper.xml 定义如下所示

<select id="getUserListByUserName"
        parameterType="String"
        resultType="map">
    select
    id, username, user_email userEmail, user_city userCity, age
    from user
    where username = #{username}
</select>

resultMap

有时候通过驼峰命名规则并不能映射到我们想要的JavaBean属性,就可以使用resultMap来实现高级结果集映射。

比如有一张user表里面有id、user_email、user_city这三个字段,有一个userVO实体类有如下几个属性

public class UserVO {
    private Integer id;
    private String email;
    private String city;
    // 省略get、set方法
}

现在需要使用MyBatis将user信息查询出来并映射到userVO实体类

接口定义如下

public UserVO getUserInfoById(Integer id);

接口对应的 Mapper.xml 定义如下所示

<resultMap id="userVO" type="com.example.mybatis.entity.UserVO">
    <!--
        指定主键类的封装规则
        id定义主键,底层会有一些优化
        column指定数据路的列
        property指定对应的JavaBean属性
        -->
    <id column="id" property="id" />
    <!--定义普通列的封装-->
    <result column="user_email" property="email" />
    <result column="user_city" property="city" />
</resultMap>
<select id="getUserInfoById" resultMap="userVO">
    select * from user where id = #{id}
</select>

多表关联查询

实际开发中不可能只是对单表进行操作,一定会涉及到多表关联查询,数据表之间的关系有三种:一对一关系、一对多关系、多对多关系。

一对一

一个学生对应一个班级,而一个班级可以对应多个学生。

CREATE TABLE `t_classes` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

CREATE TABLE `t_student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(11) DEFAULT NULL,
  `cid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `cid` (`cid`),
  CONSTRAINT `student_ibfk` FOREIGN KEY (`cid`) REFERENCES `t_classes` (`id`)
);

实体类

public class Classes {
    private Integer id;
    private String name;
    private List<Student> students;
}

public class Student {
    private Integer id;
    private String name;
    private Classes classes;
}

通过学生id查询学生信息,并且把学生班级信息一起查询出来。

接口定义如下

public Student getStudentById(Integer id);

接口对应的 Mapper.xml 定义如下所示

<resultMap id="studentResultMap" type="Student">
    <id column="sid" property="id" />
    <result column="sname" property="name" />
    <!-- 映射 classes 属性 -->
    <association property="classes" javaType="com.example.mybatis.entity.Classes">
        <id column="cid" property="id" />
        <result column="cname" property="name" />
    </association>
</resultMap>
<select id="getStudentById" resultMap="studentResultMap">
    select s.id sid,s.name sname, c.id cid, c.name cname
    from t_student s , t_classes c
    where s.cid = c.id
    and s.id = #{id}
</select>

将上面的查询语句修改为分步查询、延迟查询

<resultMap id="studentResultMap" type="com.example.mybatis.entity.Student">
    <id column="id" property="id" />
    <result column="name" property="name" />
    <!--
        映射 classes 属性
        property: 映射到JavaBean中的属性
        column: 指定某个列的值传递到 select 中的方法
        select: 表名当前属性是调用select指定的方法查出的结果
                如果是调用当前mapper中的方法, 则直接填写要调用方法的id就行了
                如果是调用其它mapper中的方法, 则需要这样填写com.xxx.mapper.XxxMapper.getClassesById
        fetchType: lazy-> 懒加载、eager-> 全部加载, 
        如果设置了懒加载模式, 那么当获取classes属性时才会从数据库中加载classes数据出来
        javaType: 映射实体类
        -->
    <association property="classes"
                 column="cid"
                 select="getClassesById"
                 javaType="com.example.mybatis.entity.Classes"
                 fetchType="lazy">
        <id column="id" property="id" />
        <result column="name" property="name" />
    </association>
</resultMap>
<select id="getStudentById" resultMap="studentResultMap">
    select s.id,s.name,s.cid
    from t_student s
    where s.id = #{id}
</select>
<select id="getClassesById" resultType="com.example.mybatis.entity.Classes">
    select c.id,c.name from t_classes c where c.id = #{id}
</select>

一对多

现在反过来查询 Classes,将级联的所有 Student 一并查询。

接口定义如下

public Classes getClassesById(Integer id);

接口对应的 Mapper.xml 定义如下所示

<resultMap id="classesResultMap" type="com.example.mybatis.entity.Classes">
    <id column="cid" property="id" />
    <result column="cname" property="name" />
    <collection property="students" ofType="com.example.mybatis.entity.Student">
        <id column="sid" property="id" />
        <result column="sname" property="name"/>
    </collection>
</resultMap>
<select id="getClassesById" resultMap="classesResultMap">
    select s.id sid,s.name sname, c.id cid, c.name cname
    from t_student s , t_classes c
    where s.cid = c.id
    and c.id = #{id}
</select>

需要注意的是 association 标签,通过设置 javaType 属性,映射实体类,collection 标签,通过设置 ofType 属性映射实体类。

将上面查询修改成分步查询、延迟查询

<resultMap id="classesResultMap" type="com.example.mybatis.entity.Classes">
    <id column="cid" property="id" />
    <result column="cname" property="name" />
    <!--
            这里的column只传递了一个字段,如果想传入多个字段可以这样写
            column="{key1=column1, key2=column2}"
            相当于封装成了一个Map, 当前查询可以这样写column="{id=cid}"
        -->
    <collection
                fetchType="lazy"
                property="students"
                select="getStudentByClassesId"
                column="cid">
    </collection>
</resultMap>
<select id="getClassesById" resultMap="classesResultMap">
    select c.id cid, c.name cname
    from t_classes c
    where c.id = #{id}
</select>
<select id="getStudentByClassesId" resultType="com.example.mybatis.entity.Student">
    select s.id , s.name from t_student s where s.cid = #{id}
</select>

多对多

多对多其实是双向的一对多关系,所以双方都是用 collection 标签设置级联,与上面的一对多是类似的。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!