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.代码讲解
这里写图片描述
就这样当我们查询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.代码讲解:
这里写图片描述

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

这里写图片描述

多对一

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

多对多

订单-商品-用户的关系
订单-用户【多对一】
订单-商品【一对多】
商品-订单【多对多】-【一个商品可以出现多个订单里,多个商品可以出现在一个订单里】
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.代码讲解:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/a656678879/article/details/79165634