zoukankan      html  css  js  c++  java
  • MyBatis:多对一表关系详解

    1,如果涉及到多表查询,必须用resultMap方式。如果用resultType方式,那么获取的信息只能放到一个类里面,而像Customer和Order这种关系,我们希望查出Customer的同时查出多个他里面的orderList集合,也就是要查询不止一种对象,就必须使用resultMap映射的方式,才能将关联到的那个类的信息拿到。

     

    2,如果把配置文件中的查询语句改为 select id,user_name fromcustomer,同时把数据库中的customer表的name字段改为user_name字段,Customer实体类中的name属性名不变,再执行查询,会发现name查不出来。因为查询结果是根据实体类的属性和返回结果集的列字段名对应的,如果不一致,则无法使用set方法注入值。

    这种问题也可以通过resultMap的方式解决,用resultMap映射一下就可以了。

    例如:定义查询sql语句是:

    <sql id="allColumn">
            id,user_name,password
        </sql>
     
        <select id="findUserById" parameterType="int" resultType="cn.domain.User">
            select <include refid="allColumn"/> from user where id=#{id}
        </select>

    也就是select id,user_name,password fromuser where id=#{id}

    而实体类User中的属性名是username,将数据库中的列名也修改成user_name,返回结果username为null。

    修改:通过resultMap方式

    <sql id="allColumn">
            id,user_name,password
        </sql>
     
        <resultMap type="cn.domain.User" id="findUserById">
            <id property="id" column="id" />
            <!-- 映射成user_name,就可以将user_name列的字段值设置到username中了 -->
            <result property="username"  column="user_name"/>
            <result property="password" column="password" />
        </resultMap>
        
        <!-- 配置成resultMap的返回类型,进行映射处理 -->
        <select id="findUserById" parameterType="int" resultMap="findUserById">
            select <include refid="allColumn"/> from user where id=#{id}
        </select>

    3,建立多对一关系---案例一

    (1)表和实体类都是用刚才创建的,只需要修改一下我们的mapper配置文件和测试用例即可。

    (2)编写OrderMapper.xml文件,查询所有Order。

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
     
    <mapper namespace="cn.test1.domain">
        <!-- 配置多对一映射关系 -->
        <resultMap type="cn.test1.domain.Order" id="orderTest">
            <id property="id" column="o_id" />
            <result property="name" column="o_name" />
            <!-- 建立多对一,通过association建立 -->
            <association property="customer" javaType="cn.test1.domain.Customer">
                <id property="id" column="id" />
                <result property="name" column="name" />
            </association>
        </resultMap>
     
        <select id="getOrderinfo" parameterType="int" resultMap="orderTest">
            select c.*,o.id as o_id,o.name as o_name from customer c,`order` o 
            where c.id = o.customer_id
        </select>
    </mapper>

    (3)编写测试用例,TestOrder.java。

    public class TestOrder {
        private SqlSessionFactory sessionFactory;
        @Before
        public void init() throws IOException {
            //初始化方法
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }
        @Test
        public void testSelect() {
            //获取session
            SqlSession session = sessionFactory.openSession();
            //查询order.
            Order order = session.selectOne("cn.test1.domain.getOrderinfo");
            System.out.println(order);
            session.close();
        }
    }

    (4)结果:报错:

    太多的结果异常,原本期望获取一个,但是获取了多个。

    原因:

    查询所有的时候,因为数据库有两条记录,所以查询结果不止一条,但是我们使用的查询方式是通过selectOne方法查找,这个方法期望返回一个结果,如果返回了多个,就报异常。返回一个还是多个不是根据数据库查询记录数来定的,而是根据产生的对象数量来定的。

    解决:

    将使用的方法改成selectList方法,就可以了:

    @Test
        public void testSelect() {
            //获取session
            SqlSession session = sessionFactory.openSession();
            //查询order.
            List<Order> orderList = 
                    session.selectList("cn.test1.domain.getOrderinfo");
            System.out.println(orderList);
            session.close();
        }

    返回结果:

    [Order[id=1, name=Iphone, customer=Customer [id=1, name=小强]orderList:[]],

     Order [id=2, name=Imac, customer=Customer[id=1, name=小强]orderList:[]]]

    3,建立多对一关系---案例二

    如果使用selectOne的方法,可以查询唯一结果,比如根据id查询。例如:

    OrderMapper.xml配置文件:

    <mapper namespace="cn.itcast.test1.domain">
        <!-- 配置多对一映射关系 -->
        <resultMap type="cn.test1.domain.Order" id="orderTest">
            <id property="id" column="o_id" />
            <result property="name" column="o_name" />
            <!-- 建立多对一,通过association建立 -->
            <association property="customer" javaType="cn.test1.domain.Customer">
                <id property="id" column="id" />
                <result property="name" column="name" />
            </association>
        </resultMap>
     
        <select id="getOrderinfo" parameterType="int" resultMap="orderTest">
            select c.*,o.id as o_id,o.name as o_name from customer c,`order` o where c.id = o.customer_id and o.id=#{id}   //添加根据id查询条件
        </select>
    </mapper>

    测试用例:

    @Test
        public void testSelect() {
            //获取session
            SqlSession session = sessionFactory.openSession();
            //查询order.
            Order order = session.selectOne("cn.itcast.test1.domain.getOrderinfo",1);
            System.out.println(order);
            session.close();
        }

    这时就可以得到根据id查询出的唯一结果。

    返回结果字段的匹配方式跟一对多是一样的。

  • 相关阅读:
    【Vjudge】P1989Subpalindromes(线段树)
    【Luogu】P3358最长k可重区间集问题(费用流)
    【未有之有】洛森设定随笔
    14-Perl 引用
    13-Perl 子程序(函数)
    12-Perl 时间日期
    11-Perl 运算符
    10-Perl 循环
    9-Perl 条件语句
    8-Perl 哈希
  • 原文地址:https://www.cnblogs.com/qingmuchuanqi48/p/13800057.html
Copyright © 2011-2022 走看看