欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MyBatis的关联映射(全)五

程序员文章站 2024-03-04 09:28:29
...

MyBatis的关联映射(全)

学习要点

一对一
一对多
多对一
多对多

目录结构

MyBatis的关联映射(全)五

一对一

一对一推荐使用唯一主外键关联,一对一一般会吧外键设置为唯一约束,下面举例子为一用户对应一个人身份账号。

1.创建身份证表和用户表并插入数据

CREATE TABLE `m_card` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '身份证id',
  `cardname` varchar(16) DEFAULT NULL COMMENT '身份证的名称',
  `cardadd` varchar(255) DEFAULT NULL COMMENT '身份证的地址',
  `cardnum` varchar(30) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(66) DEFAULT NULL,
  `password` varchar(66) DEFAULT NULL,
  `deptid` int(11) DEFAULT NULL,
  `cardid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;


INSERT INTO `mybatis`.`m_card` (`id`, `cardname`, `cardadd`, `cardnum`) VALUES ('1', '小星星', '中国', '411481199606104867');

INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('1', 'root1918178885', 'password-941904276', '1', '1');

INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('2', 'root-220114577', 'password1031926093', '1', NULL);

INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('3', 'root384722669', 'password1942141865', '1', NULL);

INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('4', 'root487129123', 'password-902996385', NULL, NULL);

INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('5', 'root1461712382', 'password-381676017', '1', NULL);

2.创建实体类User

package com.pkk.entity;

import java.io.Serializable;

/**
 * @author peikunkun
 * @version V1.0
 * @Title: MyBatisProject
 * @Package com.pkk.entity
 * @Description: <>
 * @date 2017/12/31 19:31
 */
public class User implements Serializable {

    private Integer id;
    private String username;
    private String password;
    private String cardid;

    private Card card;


    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public User(Integer id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public String getCardid() {
        return cardid;
    }


    public Card getCard() {
        return card;
    }

    public void setCard(Card card) {
        this.card = card;
    }

    public void setCardid(String cardid) {
        this.cardid = cardid;
    }



    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", cardid='" + cardid + '\'' +
                ", card=" + card +
                '}';
    }
}

3.创建实体类Dept

package com.pkk.entity;

import java.io.Serializable;

/**
 * Created by peikunkun on 2018/1/25 0025.
 */
public class Card implements Serializable {

    private Integer id;
    private String cardname;
    private String cardadd;
    private String cardnum;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getCardname() {
        return cardname;
    }

    public void setCardname(String cardname) {
        this.cardname = cardname;
    }

    public String getCardadd() {
        return cardadd;
    }

    public void setCardadd(String cardadd) {
        this.cardadd = cardadd;
    }

    public String getCardnum() {
        return cardnum;
    }

    public void setCardnum(String cardnum) {
        this.cardnum = cardnum;
    }

    @Override
    public String toString() {
        return "Card{" +
                "id=" + id +
                ", cardname='" + cardname + '\'' +
                ", cardadd='" + cardadd + '\'' +
                ", cardnum='" + cardnum + '\'' +
                '}';
    }
}

4.创建一对一的配置文件(userMapper4.xml)

<?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="com.pkk.test.mappertest.userMapper4">

    <!--一对一的关系-->
    <resultMap id="cardAndUser" type="com.pkk.entity.User">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <association property="card" column="cardid" javaType="com.pkk.entity.Card" select="selectCardById1">
            <id property="id" column="id"/>
            <result property="cardname" column="cardname"/>
            <result property="cardadd" column="cardadd"/>
            <result property="cardnum" column="cardnum"/>
        </association>
    </resultMap>

    <!---->
    <select id="selectCardById1" resultType="com.pkk.entity.Card" parameterType="int" useCache="false" timeout="15">
        SELECT m.* from m_card m where m.id=#{id}
    </select>

    <select id="selectUserById1" resultMap="cardAndUser" parameterType="int">
        SELECT  * FROM  USER  where id=#{id}
    </select>

</mapper>

5.MyBatis的总配置文件(mybatis-config.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>


    <!--指定MyBatis所用的日志具体实现-->
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>


    <!--起别名,别名的作用就是用简单明代替全限定类名-->
    <typeAliases>
        <!--
        通过package, 可以直接指定package的名字, mybatis会自动扫描你指定包下面的javabean,
        并且默认设置一个别名,默认的名字为: javabean 的首字母小写的非限定类名来作为它的别名。
        也可在javabean 加上注解@Alias 来自定义别名, 例如: @Alias(user)
        <package name="com.pkk.entity"/>
         -->
        <typeAlias alias="user" type="com.pkk.entity.User"/>
    </typeAliases>


    <!--环境配置,即连接的数据库-->
    <environments default="mysql">
        <environment id="mysql">
            <!--使用jdbc的事务提交与回滚设置-->
            <transactionManager type="JDBC"/>
            <!--配置数据源,POOLED是JDBC连接对象的数据源连接池的实现-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="username" value="***"/>
                <property name="password" value="***"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis"/>
            </dataSource>
        </environment>
    </environments>
    <!--mapper告诉了MyBatis去哪里找持久化的映射文件-->
    <mappers>
        <!--多表关联查询(全)-->
        <mapper resource="com.pkk.test/mappertest/userMapper4.xml"></mapper>
    </mappers>

</configuration>

6.测试方法

package com.pkk.test.association;

import com.alibaba.fastjson.JSONObject;
import com.pkk.entity.Dept;
import com.pkk.entity.User;
import com.pkk.test.TestUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.List;
import java.util.Map;

/**
 * Created by peikunkun on 2018/1/25 0025.
 */
public class AssociationTest1 {

    private SqlSession session = null;

    @Before
    public void before() {
        session = TestUtil.getSqlSession();
    }

    @Test
    public void AssociationTest1_12() {
        System.out.println("欢迎使用单元测试方法【AssociationTest1_12()】");
        System.out.println("此方法测试描述:【一对一的映射关联】");
        List<User> users = session.selectList("com.pkk.test.mappertest.userMapper4.selectUserById1", 1);
        System.out.println(users);
    }


    @After
    public void end() {
        TestUtil.commitAndCloseSession(session);
    }
}

7.测试工具类

package com.pkk.test;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

/**
 * Created by peikunkun on 2018/1/21 0021.
 */
public class TestUtil {


    /**
     * 获取连接
     *
     * @return
     */
    public static SqlSession getSqlSession() {
       /*获取当前mybatis配置文件*/
        InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml");
        /*创建sqlSessionFactory对象*/
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        /*创建SQLSession对象操作持久层对象*/
        SqlSession session = sqlSessionFactory.openSession();

        return session;
    }

    /**
     * 关闭连接和进行提交
     *
     * @return
     */
    public static void commitAndCloseSession(SqlSession session) {
        if (session != null) {
            session.commit();
            session.close();
        }
    }

}

8.代码讲解
MyBatis的关联映射(全)五
就这样当我们查询User的时候也会把Card查出来

一对多

数据库中维护一对多的关系一般是主外键关联,外键应该在多的一方,也就是多的一方进行维护,下面例子是一个部门对应多个用户。
1.数据库表

CREATE TABLE `dept` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '部门id',
  `deptname` varchar(50) DEFAULT NULL COMMENT '部门名称',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) DEFAULT NULL COMMENT '用户名',
  `password` varchar(32) DEFAULT NULL COMMENT '用户密码',
  `deptid` int(11) DEFAULT NULL COMMENT '部门id',
  `cardid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;


INSERT INTO `mybatis`.`dept` (`id`, `deptname`) VALUES ('1', '昆仔学习部');

INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('1', 'root1918178885', 'password-941904276', '1', '1');
INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('2', 'root-220114577', 'password1031926093', '1', NULL);
INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('3', 'root384722669', 'password1942141865', '1', NULL);

2.实体类User

package com.pkk.entity;

import java.io.Serializable;

/**
 * @author peikunkun
 * @version V1.0
 * @Title: MyBatisProject
 * @Package com.pkk.entity
 * @Description: <>
 * @date 2017/12/31 19:31
 */
public class User implements Serializable {

    private Integer id;
    private String username;
    private String password;
    private String cardid;

    private Dept dept;


    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public User(Integer id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public String getCardid() {
        return cardid;
    }


    public void setCardid(String cardid) {
        this.cardid = cardid;
    }

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }



    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", cardid='" + cardid + '\'' +
                ", dept=" + dept +
                '}';
    }
}

3.实体类Dept

package com.pkk.entity;

import java.io.Serializable;
import java.util.List;

/**
 * Created by peikunkun on 2018/1/24 0024.
 * 《部门表》
 */
public class Dept implements Serializable {

    private Integer id;
    private String deptname;

    /*因为一个部门对应多个员工,所以用集合来接收多个用户*/
    private List<User> users;

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getDeptname() {
        return deptname;
    }

    public void setDeptname(String deptname) {
        this.deptname = deptname;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "id=" + id +
                ", deptname='" + deptname + '\'' +
                ", users=" + users +
                '}';
    }
}

4.一对多的配置文件(userMapper5.xml)

<?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="com.pkk.test.mappertest.userMapper4">


    <!--一对多-->
    <resultMap id="deptAndUser" type="com.pkk.entity.Dept">
        <id property="id" column="id"/>
        <result property="deptname" column="deptname"/>
        <collection property="users" column="id" ofType="com.pkk.entity.User" javaType="ArrayList"
                    select="selectUserById2" fetchType="lazy">
            <!--数据库字段与实体字段一致不在书写-->
        </collection>
    </resultMap>

    <!--一对多-->
    <select id="selectDeptById1" resultMap="deptAndUser" parameterType="int">
        SELECT * FROM dept where id=#{id}
    </select>

    <select id="selectUserById2" resultType="com.pkk.entity.User" parameterType="int">
        SELECT  * FROM  USER  where deptid=#{deptid}
    </select>
</mapper>

5.MyBatis的总配置文件(mybatis-config.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>


    <!--指定MyBatis所用的日志具体实现-->
    <settings>
        <setting name="logImpl" value="LOG4J"/>
        <!--lazyLoadingEnabled 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。默认:true
        aggressiveLazyLoading 当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。默认:true-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>


    <!--起别名,别名的作用就是用简单明代替全限定类名-->
    <typeAliases>
        <!--
        通过package, 可以直接指定package的名字, mybatis会自动扫描你指定包下面的javabean,
        并且默认设置一个别名,默认的名字为: javabean 的首字母小写的非限定类名来作为它的别名。
        也可在javabean 加上注解@Alias 来自定义别名, 例如: @Alias(user)
        <package name="com.pkk.entity"/>
         -->
        <typeAlias alias="user" type="com.pkk.entity.User"/>
    </typeAliases>


    <!--环境配置,即连接的数据库-->
    <environments default="mysql">
        <environment id="mysql">
            <!--使用jdbc的事务提交与回滚设置-->
            <transactionManager type="JDBC"/>
            <!--配置数据源,POOLED是JDBC连接对象的数据源连接池的实现-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="username" value="root"/>
                <property name="password" value="admin"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis"/>
            </dataSource>
        </environment>
    </environments>
    <!--mapper告诉了MyBatis去哪里找持久化的映射文件-->
    <mappers>
        <!--多表关联查询(全)-->
        <mapper resource="com.pkk.test/mappertest/userMapper5.xml"></mapper>

    </mappers>

</configuration>

6.测试类以及工具类(工具类见一对一)

package com.pkk.test.association;

import com.alibaba.fastjson.JSONObject;
import com.pkk.entity.Dept;
import com.pkk.entity.User;
import com.pkk.test.TestUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.List;
import java.util.Map;

/**
 * Created by peikunkun on 2018/1/25 0025.
 */
public class AssociationTest1 {

    private SqlSession session = null;

    @Before
    public void before() {
        session = TestUtil.getSqlSession();
    }




    @Test
    public void AssociationTest1_38() {
        System.out.println("欢迎使用单元测试方法【AssociationTest1_38()】");
        System.out.println("此方法测试描述:【一对多的测试】");
        List<Dept> depts = session.selectList("com.pkk.test.mappertest.userMapper4.selectDeptById1", 1);
        System.out.println(depts);
    }


    @After
    public void end() {
        TestUtil.commitAndCloseSession(session);
    }
}

7.代码讲解:
MyBatis的关联映射(全)五

注意要点:
1.一对多中一般在只查询一的一方的时候,不需要查询多的一方的时候,这时候我们可以设置懒加载,这样我们就会不用去查询多的一方的信息
2.一对多的关联的集合对象,都应该设置成懒加载3.使用懒加载还需要配置setting,否则无效。

MyBatis的关联映射(全)五

多对一

代码举例参考MyBatis的简单多表关联映射
从下面的图片可以看出,其实一对多和多对一就是站的角度不同,一对多返回的是关联对象是集合对象(配置中用collection),多对一返回的关联对象通常是实体对象(配置中用association )
MyBatis的关联映射(全)五

多对多

订单-商品-用户的关系
订单-用户【多对一】
订单-商品【一对多】
商品-订单【多对多】-【一个商品可以出现多个订单里,多个商品可以出现在一个订单里】
1.创建数据库表
数据库创建说明
用户表:用户体系,有了用户体系才会有开展各种业务可能
订单表:一个用户可以有多个订单
图书表:一个订单中可以包含多本书,一本书也可以在多个订单中选购[多对多]
关联表:主要是为了解决表与表之间多与多的关联,

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) DEFAULT NULL COMMENT '用户名',
  `password` varchar(32) DEFAULT NULL COMMENT '用户密码',
  `deptid` int(11) DEFAULT NULL COMMENT '部门id',
  `cardid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;


INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('1', 'root1918178885', 'password-941904276', '1', '1');
INSERT INTO `mybatis`.`user` (`id`, `username`, `password`, `deptid`, `cardid`) VALUES ('2', 'root-220114577', 'password1031926093', '1', NULL);


CREATE TABLE `m_order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `code` varchar(50) DEFAULT NULL COMMENT '订单编码',
  `total` int(11) DEFAULT NULL COMMENT '订单总金额(订单总金额是属于订单的属性)',
  `user_id` int(11) DEFAULT NULL COMMENT '用户id',
  PRIMARY KEY (`id`),
  KEY `fk_userid` (`user_id`),
  CONSTRAINT `fk_userid` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;



INSERT INTO `mybatis`.`m_order` (`id`, `code`, `total`, `user_id`) VALUES ('1', 'abcd789456123', '112', '1');
INSERT INTO `mybatis`.`m_order` (`id`, `code`, `total`, `user_id`) VALUES ('2', 'abcdfeh789456123', '674', '1');


CREATE TABLE `m_book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL COMMENT '图书名称',
  `price` varchar(11) DEFAULT NULL COMMENT '图书金额',
  `remark` varchar(255) DEFAULT NULL COMMENT '图书评价',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

INSERT INTO `mybatis`.`m_book` (`id`, `name`, `price`, `remark`) VALUES ('1', 'Spring图书', '56', '不错');
INSERT INTO `mybatis`.`m_book` (`id`, `name`, `price`, `remark`) VALUES ('2', 'Hibernate图书', '88', '可以');
INSERT INTO `mybatis`.`m_book` (`id`, `name`, `price`, `remark`) VALUES ('3', 'MyBatis图书', '66', '挺好');


CREATE TABLE `m_item` (
  `order_id` int(11) NOT NULL DEFAULT '0' COMMENT '订单编号',
  `book_id` int(11) NOT NULL DEFAULT '0' COMMENT '图书编号',
  `amount` int(11) DEFAULT NULL COMMENT '图书总量(一次订单中一种图书在同一用户下的下单数量)',
  PRIMARY KEY (`order_id`,`book_id`),
  KEY `book_id` (`book_id`),
  CONSTRAINT `m_item_ibfk_1` FOREIGN KEY (`order_id`) REFERENCES `m_order` (`id`),
  CONSTRAINT `m_item_ibfk_2` FOREIGN KEY (`book_id`) REFERENCES `m_book` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `mybatis`.`m_item` (`order_id`, `book_id`, `amount`) VALUES ('1', '1', '2');
INSERT INTO `mybatis`.`m_item` (`order_id`, `book_id`, `amount`) VALUES ('2', '1', '3');
INSERT INTO `mybatis`.`m_item` (`order_id`, `book_id`, `amount`) VALUES ('2', '2', '2');
INSERT INTO `mybatis`.`m_item` (`order_id`, `book_id`, `amount`) VALUES ('2', '3', '5');

2.创建实体类(user)

package com.pkk.entity;

import java.io.Serializable;
import java.util.List;

/**
 * @author peikunkun
 * @version V1.0
 * @Title: MyBatisProject
 * @Package com.pkk.entity
 * @Description: <>
 * @date 2017/12/31 19:31
 */
public class User implements Serializable {

    private Integer id;
    private String username;
    private String password;
    private String cardid;

    /*用户与订单是一对多的关系,即一个用户可以有多个订单*/
    private List<Order> orders;




    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public User(Integer id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public List<Order> getOrders() {
        return orders;
    }

    public void setOrders(List<Order> orders) {
        this.orders = orders;
    }

    public String getCardid() {
        return cardid;
    }




    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", cardid='" + cardid + '\'' +
                ", orders=" + orders +
                '}';
    }
}

3.创建实体类(Order)

package com.pkk.entity;

import java.awt.print.Book;
import java.io.Serializable;
import java.util.List;

/**
 * Created by peikunkun on 2018/1/26 0026.
 */
public class Order implements Serializable {

    private Integer id;
    private String code;//订单编号
    private Integer total;//订单总金额
    /*订单和用户是多对一的关系,即一个订单只属于一个用户*/
    private User user;

    /*订单和图书是多对多的关系,即一个订单可以是可以包含多个商品,所以返回一个list*/
    private List<Book> books;


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public Integer getTotal() {
        return total;
    }

    public void setTotal(Integer total) {
        this.total = total;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public List<Book> getBooks() {
        return books;
    }

    public void setBooks(List<Book> books) {
        this.books = books;
    }

    @Override
    public String toString() {
        return "Order{" +
                "id=" + id +
                ", code='" + code + '\'' +
                ", total=" + total +
                ", user=" + user +
                ", books=" + books +
                '}';
    }
}

4.创建实体类(Book)

package com.pkk.entity;

import java.util.List;

/**
 * Created by peikunkun on 2018/1/26 0026.
 */
public class Book {

    private Integer id;
    private String name;//图书名
    private String price;//图书单价
    private String remark;//图书说明评价

    /*图书和订单是多对多的关系,即一本图书可以存在于多个订单中,所以返回的是List集合*/
    private List<Order> orders;

    public List<Order> getOrders() {
        return orders;
    }

    public void setOrders(List<Order> orders) {
        this.orders = orders;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }


    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", price='" + price + '\'' +
                ", remark='" + remark + '\'' +
                ", orders=" + orders +
                '}';
    }
}

5.配置文件(userMapper5.xml)

<?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="com.pkk.test.mappertest.userMapper5">

    <!--***********************************一对多的配置  Begin************************************************-->
    <!--本配置文件是针对于多对多的配置文件-->
    <!--查询用户的信息,返回的实体映射,包含用户和订单的信息【一对多都是使用的懒加载】   ****第二步-->
    <resultMap id="userAndOrder" type="com.pkk.entity.User">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <collection property="orders" column="id" javaType="ArrayList" ofType="com.pkk.entity.Order"
                    fetchType="lazy" select="selectOrderByUserId">
            <id property="id" column="id"/>
            <result property="code" column="code"/>
            <result property="total" column="total"/>
        </collection>
    </resultMap>


    <!--查询用户的信息   ****第一步-->
    <select id="selectUserInFoByUserId" resultMap="userAndOrder" timeout="20" parameterType="int">
        select * from USER where id =#{id}
    </select>

    <!--根据用户的id查询订单的信息-->
    <select id="selectOrderByUserId" parameterType="int" resultType="com.pkk.entity.Order">
        select * from m_order  where user_id=#{id}
    </select>

    <!--***********************************一对多的配置  End************************************************-->


    <!--***********************************多对多的配置  Begin************************************************-->

    <resultMap id="allInfoByOrder" type="com.pkk.entity.Order">
        <!--这里用的是oid,因为在查询的时候使用了别名-->
        <id column="oid" property="id"/>
        <result column="code" property="code"/>
        <result column="total" property="total"/>
        <!--多个订单和一个用户的关系-->
        <association property="user" column="user_id" javaType="com.pkk.entity.User">
            <id column="id" property="id"/>
            <result column="username" property="username"/>
            <result column="password" property="password"/>
        </association>
        <!--多对多的关联映射{订单}对{图书}-->
        <collection property="books" column="oid" javaType="ArrayList" ofType="com.pkk.entity.Book" fetchType="lazy"
                    select="selectBookByOrderId">
            <id property="id" column="id"/>
            <result property="name" column="name"/>
            <result property="price" column="price"/>
            <result property="remark" column="remark"/>
        </collection>
    </resultMap>
    <!--用户与订单关联,根据订单的id查询出订单和用户的信息-->
    <select id="selectOrderById" resultMap="allInfoByOrder" parameterType="int">
        select u.*,o.id as oid,o.code,o.total  from user u,m_order o where u.id = o.user_id and o.id =#{id}
    </select>
    <!--依据关联表查询【依据订单查询图书信息】-->
    <select id="selectBookByOrderId" timeout="20" parameterType="int" resultType="com.pkk.entity.Book">
        select *from m_book b where b.id in (select i.book_id FROM m_item i where i.order_id =#{id})
    </select>

    <!--***********************************多对多的配置  End************************************************-->

</mapper>

6.总MyBatis配置文件(mybatis-config.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>


    <!--指定MyBatis所用的日志具体实现-->
    <settings>
        <setting name="logImpl" value="LOG4J"/>
        <!--lazyLoadingEnabled 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。默认:true
        aggressiveLazyLoading 当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。默认:true-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>


    <!--起别名,别名的作用就是用简单明代替全限定类名-->
    <typeAliases>
        <!--
        通过package, 可以直接指定package的名字, mybatis会自动扫描你指定包下面的javabean,
        并且默认设置一个别名,默认的名字为: javabean 的首字母小写的非限定类名来作为它的别名。
        也可在javabean 加上注解@Alias 来自定义别名, 例如: @Alias(user)
        <package name="com.pkk.entity"/>
         -->
        <typeAlias alias="user" type="com.pkk.entity.User"/>
    </typeAliases>


    <!--环境配置,即连接的数据库-->
    <environments default="mysql">
        <environment id="mysql">
            <!--使用jdbc的事务提交与回滚设置-->
            <transactionManager type="JDBC"/>
            <!--配置数据源,POOLED是JDBC连接对象的数据源连接池的实现-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="username" value="root"/>
                <property name="password" value="admin"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis"/>
            </dataSource>
        </environment>
    </environments>
    <!--mapper告诉了MyBatis去哪里找持久化的映射文件-->
    <mappers>
        <!--多表关联查询【多对多】-->
        <mapper resource="com.pkk.test/mappertest/userMapper5.xml"></mapper>

    </mappers>

</configuration>

7.测试类(测试工具类【同上面的代码示例】)

package com.pkk.test.association;

import com.pkk.entity.Dept;
import com.pkk.entity.User;
import com.pkk.test.TestUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

/**
 * Created by peikunkun on 2018/1/25 0025.
 * 《多对多的关联数据》
 */
public class AssociationTest2 {

    private SqlSession session = null;

    @Before
    public void before() {
        session = TestUtil.getSqlSession();
    }

    @Test
    public void AssociationTest1_12() {
        System.out.println("欢迎使用单元测试方法【AssociationTest1_12()】");
        System.out.println("此方法测试描述:【一对一的映射关联】");
        List<User> users = session.selectList("com.pkk.test.mappertest.userMapper5.selectUserInFoByUserId", 1);
        System.out.println(users);
    }

    @Test
    public void AssociationTest1_35() {
        System.out.println("欢迎使用单元测试方法【AssociationTest1_12()】");
        System.out.println("此方法测试描述:【一对一的映射关联】");
        List<User> users = session.selectList("com.pkk.test.mappertest.userMapper5.selectOrderById", 2);
        System.out.println(users);
    }


    @After
    public void end() {
        TestUtil.commitAndCloseSession(session);
    }
}

8.代码讲解:
MyBatis的关联映射(全)五