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查询出的唯一结果。

 

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

 

posted @ 2020-10-11 23:05  King-DA  阅读(159)  评论(0编辑  收藏  举报