四,MyBatis结果集映射和表与表之间映射

原创 2016年08月31日 11:24:51

1,结果集映射ResultMaps

1.1,简单ResultMap

一个映射了查询结果和User JavaBean的简单的resultMap

<resultMap type="User" id="UserResult">
    <id  property="id" column="user_id"/>
    <result property="name" column="user_name"/>
    <result property="email" column="user_email"/>
    <result property="age" column="user_age"/>
</resultMap>
<select id="selectAllUser" resultMap="UserResult">
    SELECT * FROM USER
</select>

<select id="selectUserById" resultMap="UserResult" parameterType="int">
    select * from user where user_id = #{id}
</select>


表示 resultMap 的 UserResult id 值应该在此名空间内是唯一的。并且 type 属性应该是完全限定类名或者是返回类型的别名。

<result>子元素被用来将一个 resultset 列映射到 JavaBean 的一个属性中。

<id>元素和<result>元素功能相同,不过它被用来映射到唯一标识属性, 用来区分和比较对象 (一般和主键列相对应) 。

1.2,返回集合map

<select id="selectUserByIdReturnMap" resultType="map" parameterType="int">
    select * from user where user_id = #{id}
</select>
@Test
    public void findUserByIdReturnMap(){
        SqlSession session = MyBatisUtil.openSession();
        UserMapper userMapper = session.getMapper(UserMapper.class);
        Map<String, Object> userMap = userMapper.selectUserByIdReturnMap(1);
        System.out.println("用户ID: "+userMap.get("user_id"));//此处获取的应该是数据表中的列名称,而不是实体类属性名称。
        System.out.println("用户EMAIL: "+userMap.get("user_email"));
        System.out.println("用户NAME: "+userMap.get("user_name"));
        System.out.println("用户AGE: "+userMap.get("user_age"));
    }

1.3,拓展ResultMap

<resultMap type="Student" id="StudentResult">
    <id property="studId" column="stud_id" />
    <result property="name" column="name" />
    <result property="email" column="email" />
    <result property="phone" column="phone" />
</resultMap>
<resultMap type="Student" id="StudentWithAddressResult" extends="StudentResult">
    <result property="address.addrId" column="addr_id" />
    <result property="address.street" column="street" />
    <result property="address.city" column="city" />
    <result property="address.state" column="state" />
    <result property="address.zip" column="zip" />
    <result property="address.country" column="country" />
</resultMap>

如果只想映射Student数据,可以使用id为StudentResult的resultMap

<select id="findStudentById" parameterType="int" resultMap="StudentResult">
    SELECT * FROM STUDENTS WHERE STUD_ID=#{studId}
</select>

如果想映射Student数据和Address数据,可以使用id为StudentWithAddressResult的resultMap

<select id="selectStudentWithAddress" parameterType="int" resultMap="StudentWithAddressResult">
    SELECT STUD_ID, NAME, EMAIL, PHONE, A.ADDR_ID, STREET, CITY, STATE, ZIP, COUNTRY
    FROM STUDENTS S 
    LEFT OUTER JOIN ADDRESSES A ON S.ADDR_ID=A.ADDR_ID
    WHERE STUD_ID=#{studId}
</select>

2,表之间映射

2.1,一对一映射

2.1.1,内联的方式实现一对一的映射

<resultMap type="User" id="UserWithAddressResult">
        <id  property="id" column="user_id"/>
        <result property="name" column="user_name"/>
        <result property="email" column="user_email"/>
        <result property="age" column="user_age"/>
        <result property="address.addrId" column="addr_id"/>
        <result property="address.street" column="street"/>
        <result property="address.city" column="city"/>
        <result property="address.state" column="state"/>
        <result property="address.zip" column="zip"/>
        <result property="address.country" column="country"/>
</resultMap>
<select id="selectUserWithAddress" parameterType="int" resultMap="UserWithAddressResult">
        select user_id, user_name, user_age, user_email, u.addr_id, city, state, zip, country
        from user u left join address a on
        u.addr_id = a.addr_id
        where user_id = #{id}
  </select>

映射器接口:

public interface UserMapper {

    void insertUser(User user);

    void insertUserWithUseGengerateKey(User user);

    Integer updateUser(User user);

    Integer deleteUserById(Integer id);

    List selectAllUser();

    User selectUserById(Integer id);

    Map<String, Object> selectUserByIdReturnMap(Integer id);

    User selectUserWithAddress(Integer id);
}

实体类:

public class Address {

    private Integer addrId;
    private String street;
    private String city;
    private String state;
    private String zip;
    private String country;

    ......
public class User {

    private Integer id;
    private String name;
    private String email;
    private Integer age;
    private Address address;

    ......

测试代码:

    @Test
    public void selectUserWithAddress(){
        SqlSession session = MyBatisUtil.openSession();
        UserMapper userMapper = session.getMapper(UserMapper.class);
        User user = userMapper.selectUserWithAddress(1);
        System.out.println("用户详细信息:"+user);
    }

2.1.2,嵌套的方式实现一对一的映射

只需要改变resultMap中的配置,其他无需变化

<resultMap type="Address" id="AddressResult">
        <id property="addrId" column="addr_id" />
        <result property="street" column="street" />
        <result property="city" column="city" />
        <result property="state" column="state" />
        <result property="zip" column="zip" />
        <result property="country" column="country" />
    </resultMap>

    <resultMap type="User" id="UserWithAddressResult">
        <id  property="id" column="user_id"/>
        <result property="name" column="user_name"/>
        <result property="email" column="user_email"/>
        <result property="age" column="user_age"/>
        <association property="address" resultMap="AddressResult">
    </resultMap>
<select id="selectUserWithAddress" parameterType="int" resultMap="UserWithAddressResult">
        select user_id, user_name, user_age, user_email, u.addr_id, city, state, zip, country
        from user u left join address a on
        u.addr_id = a.addr_id
        where user_id = #{id}
  </select>

2.1.3,嵌套查询的方式实现一对一的映射

<resultMap type="Address" id="AddressResult">
    <id property="addrId" column="addr_id" />
    <result property="street" column="street" />
    <result property="city" column="city" />
    <result property="state" column="state" />
    <result property="zip" column="zip" />
    <result property="country" column="country" />
</resultMap>
<select id="findAddressById" parameterType="int" resultMap="AddressResult">
    SELECT * FROM ADDRESSE WHERE ADDR_ID=#{id}
</select>
<resultMap type="User" id="UserWithAddressResult">
    <id  property="id" column="user_id"/>
    <result property="name" column="user_name"/>
    <result property="email" column="user_email"/>
    <result property="age" column="user_age"/>
    <association property="address" column="addr_id" select="findAddressById">
</resultMap>
<select id="findUserWithAddress" parameterType="int" resultMap="UserWithAddressResult">
    SELECT * FROM user WHERE user_id = #{id}
</select>

在此方式中,元素的 select 属性被设置成了 id 为 findAddressById 的语句。这里,两个分开的SQL 语句将会在数据库中执行,第一个调用 findUserById 加载 user 信息,而第二个调用 findAddressById 来加载 address 信息。addr_id 列的值将会被作为输入参数传递给selectAddressById 语句。

    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user = mapper.selectUserWithAddress(id);
    System.out.println(user);
    System.out.println(user.getAddress());

2.2,一对多映射(代码取自《Java Persistence With MyBatis 3》)

使用元素将 一对多类型的结果 映射到 一个对象集合上。以老师和课程的关系说明一对多的关系。

public class Course
{
    private Integer courseId;
    private String name;
    private String description;
    private Date startDate;
    private Date endDate;
    private Integer tutorId;
    //setters & getters
}
public class Tutor
{
    private Integer tutorId;
    private String name;
    private String email;
    private Address address;
    private List courses;
    / setters & getters
}

2.2.1,内嵌结果ResultMap实现一对多映射

<resultMap type="Course" id="CourseResult">
    <id column="course_id" property="courseId" />
    <result column="name" property="name" />
    <result column="description" property="description" />
    <result column="start_date" property="startDate" />
    <result column="end_date" property="endDate" />
</resultMap>
<resultMap type="Tutor" id="TutorResult">
    <id column="tutor_id" property="tutorId" />
    <result column="tutor_name" property="name" />
    <result column="email" property="email" />
    <collection property="courses" resultMap="CourseResult" />
</resultMap>
<select id="findTutorById" parameterType="int" resultMap="TutorResult">
    SELECT T.TUTOR_ID, T.NAME AS TUTOR_NAME, EMAIL, C.COURSE_ID,
    C.NAME, DESCRIPTION, START_DATE, END_DATE
    FROM TUTORS T LEFT OUTER JOIN COURSES C ON T.TUTOR_ID=C.TUTOR_ID
    WHERE T.TUTOR_ID=#{tutorId}
</select>

2.2.2,嵌套select语句实现一对多映射

<resultMap type="Course" id="CourseResult">
    <id column="course_id" property="courseId" />
    <result column="name" property="name" />
    <result column="description" property="description" />
    <result column="start_date" property="startDate" />
    <result column="end_date" property="endDate" />
</resultMap>
<resultMap type="Tutor" id="TutorResult">
    <id column="tutor_id" property="tutorId" />
    <result column="tutor_name" property="name" />
    <result column="email" property="email" />
    <association property="address" resultMap="AddressResult" />
    <collection property="courses" column="tutor_id" select="findCoursesByTutor" />
</resultMap>
<select id="findTutorById" parameterType="int" resultMap="TutorResult">
    SELECT T.TUTOR_ID, T.NAME AS TUTOR_NAME, EMAIL
    FROM TUTORS T WHERE T.TUTOR_ID=#{tutorId}
</select>
<select id="findCoursesByTutor" parameterType="int" resultMap="CourseResult">
    SELECT * FROM COURSES WHERE TUTOR_ID=#{tutorId}
</select>

嵌套 Select 语句查询会导致 N+1 选择问题。 首先,主查询将会执行(1 次) ,对于主查询返回的每一行,另外一个查询将会被执行(主查询 N 行,则此查询 N 次) 。 对于大型数据库而言,这会导致很差的性能问题。

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

使用Mybatis时实体类属性名和表中的字段名不一致导致结果无法映射到实体类的解决办法

开发中,实体类中的属性名和对应的表中的字段名不一定都是完全相同的,这样可能会导致用实体类接收返回的结果时导致查询到的结果无法映射到实体类的属性中,那么该如何解决这种字段名和实体类属性名不相同的冲突呢?...

mybatis的高级结果集映射

1    一对一查询 案例:查询所有订单信息,关联查询下单用户信息。   注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

Mybatis3源码分析(16)-Sql解析执行-结果集映射(ResultSetHandler)

在PreparedStatementHandler中的query()方法中,是用ResultHandler来完成结果集的映射的。 public List query(Statement stat...

MyBatis结果集映射(ResultMap)

Mybatis的查询可以将查询出的结果集转换成Java对象。ResultMap有以下几种用途: 1、如果数据表的列名和Java对象的属性名不一致,在ResultMap中可以进行关联 2、定义一对一...

hibernate纯sql查询结果集映射为DTO(VO,DO)

感谢glamey兄弟的文章,正好解决了当前遇到的问题。原文链接如下:http://glamey.iteye.com/blog/721019 假设我们现在有一个DTO,其属性包括两张表的属性,我...

结果集映射,一些标签的用法

标签: 作用:可以引用外部properties配置文件的内容 属性: 1.resource:引用类路径下的资源 2.url:引入网络路径或者磁盘路径下的资源 标签: 作用:为Java类型起...

Hibernate对原生sql处理及结果集和VO的映射

在action层明明看到有list值,传到jsp层就是不显示,后debug跟到jsp,发现也是可以循环的,可“奇怪”的就是不显示。 经过一番折腾,才发现经过sql获得的List不是“理所当然“的Lis...

复杂结果集映射

MyBatis 的 ResultMap 可以进行复杂的关联关系映射: 映射管理关系 集合映射 数据量太大时候,小心内存泄漏出问题 替换为分页查询 1.引子 在一个在线评论系统中,用户可以发帖,其...

SSM框架之MyBatis(二)--多表查询及查询结果映射

使用MyBatis这一强大的框架可以解决很多赋值的问题,其中对于子配置文件中的小细节有很多需要注意的地方,使用这个框架后主要就是对于配置文件的编写和配置。 今天我写了一个多表查询,表的基本结构如下: ...

hibernate将sql或hql查询结果集映射为实体类 不需要映射文件

感谢glamey兄弟的文章,正好解决了当前遇到的问题。原文链接如下:http://glamey.iteye.com/blog/721019         假设我们现在有一个DTO,其属性包括两...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)