记录Kite的学习历程之 Mybatis多表查询

Kite学习框架的第六天

首先今天的学习内容需要在数据库mysql中创建3个表 分别是
account
表的创建

CREATE TABLE `account` (
  `ID` int(11) NOT NULL COMMENT '编号',
  `UID` int(11) default NULL COMMENT '用户编号',
  `MONEY` double default NULL COMMENT '金额',
  PRIMARY KEY  (`ID`),
  KEY `FK_Reference_8` (`UID`),
  CONSTRAINT `FK_Reference_8` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

数据的插入(注意要加一定的在插入语句前后加几行代码)

SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT;
SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS;
SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION;
SET NAMES utf8;
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO';
SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0; 

insert  into `account`(`ID`,`UID`,`MONEY`) 
	values (1,1,1000),(2,3,1000),(3,1,2000);
	
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT;
SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS;
SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION;
SET SQL_NOTES=@OLD_SQL_NOTES; 

记录Kite的学习历程之 Mybatis多表查询_第1张图片
创建Role表

CREATE TABLE `role` (
  `ID` INT(11) NOT NULL COMMENT '编号',
  `ROLE_NAME` VARCHAR(30) DEFAULT NULL COMMENT '角色名称',
  `ROLE_DESC` VARCHAR(60) DEFAULT NULL COMMENT '角色描述',
  PRIMARY KEY  (`ID`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

插入数据:

INSERT  INTO `role`(`ID`,`ROLE_NAME`,`ROLE_DESC`)
	 VALUES (1,'院长','管理整个学院'),(2,'总裁','管理整个公司'),(3,'校长','管理整个学校');

Role表截图:
记录Kite的学习历程之 Mybatis多表查询_第2张图片

创建user_role表

CREATE TABLE `user_role` (
  `UID` INT(11) NOT NULL COMMENT '用户编号',
  `RID` INT(11) NOT NULL COMMENT '角色编号',
  PRIMARY KEY  (`UID`,`RID`),
  KEY `FK_Reference_10` (`RID`),
  CONSTRAINT `FK_Reference_10` FOREIGN KEY (`RID`) REFERENCES `role` (`ID`),
  CONSTRAINT `FK_Reference_9` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

插入数据:

SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT;
SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS;
SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION;
SET NAMES utf8;
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO';
SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0; 

INSERT  INTO `user_role`(`UID`,`RID`) VALUES (1,1),(2,1),(2,2);

SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT;
SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS;
SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION;
SET SQL_NOTES=@OLD_SQL_NOTES; 

截图:
记录Kite的学习历程之 Mybatis多表查询_第3张图片
这时才可以进行今天的操作

1. Mybatis 多表查询之一对多

1.1 一对一查询(多对一)

需求 :查询所有账户信息,关联查询下单用户信息。
注意: 因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询。如 果从用户信息出发查询用户下的账户信息则为一对多查询,因为一个用户可以有多个账户

1.1.1 在domain 定义账户信息的实体类 Account

public class Account implements Serializable {
    private Integer id;
    private Integer uid;
    private Double money;
    //在从从表的实体类中加入主表的实体类
    private User user;

    public User getUser() {
        return user;
    }

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

    public Integer getId() {
        return id;
    }

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

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", uid=" + uid +
                ", money=" + money +
                '}';
    }
}

1.1.2 编写sql语句,现在mysql下执行

实现查询账户信息时,也要查询账户所对应的用户信息。

SELECT 
  account.*,
  user.username,
  user.address 
FROM
  account,
  USER 
WHERE account.uid = user.id 

结果图:
记录Kite的学习历程之 Mybatis多表查询_第4张图片

1.1.3 定义封装以上信息的AccountUser类

为了能够封装上面 SQL 语句的查询结果,定义 AccountCustomer 类中要包含账户信息同时还要包含用户信 息,所以我们要在定义 AccountUser 类时可以继承 User 类。

public class AccountUser extends Account {

    private String username;
    private String address;

    public String getUsername() {
        return username;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return  "AccountUser{"
                +super.toString() + '\'' +
                "username='" + username + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

1.1.4 在dao包中定义一个AccountDao接口并添加查找账户的方法

public interface AccountDao {

    /**
     * 查询所有账户的方法
     */
    List<Account> findAllAccount();

    /**
     * 查询所有用户,并且待用用户名名称和地址
     * @return
     */
    List<AccountUser> findUserAccount();
}

1.1.5 重新配置一个AccountDao.xml文件(注意路径要跟UserDao.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.kiteYY.dao.AccountDao">


    <!--定义封装account和user的resultMao-->
    <resultMap id="accountUserMap" type="account">
        <id property="id" column="aid"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!--通过一对一的关系映射:封装user的内容-->
        <association property="user" column="uid" javaType="user">
            <id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="sex" column="sex"></result>
            <result property="address" column="address"></result>
            <result property="birthday" column="birthday"></result>
        </association>
    </resultMap>

    <!--抽取重复的sql语句-->
    <sql id="defaultFindAll">
        SELECT account.`ID` AS aid, account.`UID`, account.`MONEY`, user.* FROM account, USER WHERE account.`UID` = user.`id`;
    </sql>




    <!--查询所有的账户信息和包含的用户信息-->
    <select id="findUserAccount" resultType="AccountUser">
     SELECT account.*,user.`username`, user.`address` FROM account,USER WHERE user.id = account.`UID`;
    </select>


    <select id="findAllAccount" resultMap="accountUserMap">
        <include refid="defaultFindAll"></include>
    </select>


    <select id="findById" parameterType="INT" resultType="user">
        select * from user where id=#{userid};
    </select>


</mapper>


1.1.6 添加测试类

public class MyBatisTest {

    private InputStream in;
    private SqlSession session;
    private AccountDao accountDao;

    @Before  //在执行测试方法前进行执行
    public void init(){
        try {
            //1.读取配置文件获取字节输入流
            in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.获取SqlSessionFactor工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory build = builder.build(in);
            session = build.openSession();    //如果没openSession(true) :则是自动提交
            //3.获取代理对象
            accountDao =  session.getMapper(AccountDao.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @After //在执行测试方法后进行执行
    public void destroy(){

        //事务的提交
        session.commit();
        //5.释放资源
        session.close();
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 查询所有的用户信息和相关的账户信息
     */
    @Test
    public void findAccountUserTest(){
        List<AccountUser> userAccount = accountDao.findUserAccount();
        for (AccountUser accountUser : userAccount) {
            System.out.println("-------每一个account信息-----------");
            System.out.println(accountUser);

        }
    }


    /**
     * 测试查询所所有的账户信息
     */
    @Test
    public void findAllAccountTest(){
        List<Account> allAccount = accountDao.findAllAccount();
        for (Account account : allAccount) {
            System.out.println("-------每一个account信息-----------");
            System.out.println(account);
            System.out.println(account.getUser());
        }
    }
}

测试类的方法添加了封装了User的account查询方法
都运行一下 结果图
findAllAccountTest() 测试结果
记录Kite的学习历程之 Mybatis多表查询_第5张图片

findAccountUserTest() 测试结果:
记录Kite的学习历程之 Mybatis多表查询_第6张图片
还有一个userTest类中的测试类

package com.kiteYY.test;

import com.kiteYY.dao.AccountDao;
import com.kiteYY.dao.UserDao;
import com.kiteYY.domain.Account;
import com.kiteYY.domain.AccountUser;
import com.kiteYY.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class userTest {

    private InputStream in;
    private SqlSession session;
    private UserDao userDao;

    @Before  //在执行测试方法前进行执行
    public void init(){
        try {
            //1.读取配置文件获取字节输入流
            in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.获取SqlSessionFactor工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory build = builder.build(in);
            session = build.openSession();    //如果没openSession(true) :则是自动提交
            //3.获取代理对象
            userDao =  session.getMapper(UserDao.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @After //在执行测试方法后进行执行
    public void destroy(){

        //事务的提交
        session.commit();
        //5.释放资源
        session.close();
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }





    /**
     * 测试查询所所有的账户信息
     */
    @Test
    public void findAllTest(){
        List<User> allAccount = userDao.findAll();
        for (User account : allAccount) {
            System.out.println("-------每一个user的信息-----------");
            System.out.println(account);
            System.out.println(account.getAccount());
        }
    }
}

结果图:
这个是在User中封装了account的信息
记录Kite的学习历程之 Mybatis多表查询_第7张图片

2. Mybatis 多表查询之多对多

这个需要用到创建的user表,user_role表,role表 其中user_role表为中间表

2.1 实现 Role 到 User 多对多

2.1.1 首先为了实现需求在mysql中测试查询语句,用左外连接进行查询,左外连接会返回左表的值

SELECT 
  user.*,
  role.`ID` AS rid,
  role.`ROLE_NAME`,
  role.`ROLE_DESC` 
FROM
  role 
  LEFT OUTER JOIN user_role 
    ON role.`ID` = user_role.`RID` 
  LEFT OUTER JOIN USER 
    ON user.id = user_role.`UID` 

结果图:
记录Kite的学习历程之 Mybatis多表查询_第8张图片

2.1.2 在domain中编写Role实体类

public class Role implements Serializable {
    private Integer roleId;
    private String roleName;
    private String roleDesc;

    //多对多的映射关系:一个角色可以赋予多个用户
    private List<User> users;

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

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

    public Integer getRoleId(){
        return roleId;
    }

    public void setRoleId(Integer roleId) {
        this.roleId = roleId;
    }

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    public String getRoleDesc() {
        return roleDesc;
    }

    public void setRoleDesc(String roleDesc) {
        this.roleDesc = roleDesc;
    }

    @Override
    public String toString() {
        return "Role{" +
                "roleId=" + roleId +
                ", roleName='" + roleName + '\'' +
                ", roleDesc='" + roleDesc + '\'' +
                '}';
    }
}

2.1.3 编写持久层接口RoleDao

就一个方法查询角色信息 findAll()

public interface RoleDao {
    /**
     * 查询所有角色
     * @return
     */
    List<Role> findAll();
}

2.1.4 编写RoleDao.xml的配置文件信息

其中:在rolr中分装了user实体类的信息,配置文件中的封装信息是今天学习的中点

<?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.kiteYY.dao.RoleDao">
    <resultMap id="RoleMap" type="role">
        <id property="roleId" column="rid"></id>
        <result property="roleName" column="role_name"></result>
        <result property="roleDesc" column="role_desc"></result>
        <collection property="users" ofType="user">
            <id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="sex" column="sex"></result>
            <result property="address" column="address"></result>
            <result property="birthday" column="birthday"></result>
        </collection>
    </resultMap>
    <select id="findAll" resultMap="RoleMap">
        SELECT
          user.*,
          role.`ID` AS rid,
          role.`ROLE_NAME`,
          role.`ROLE_DESC`
        FROM
          role
          LEFT OUTER JOIN user_role
            ON role.`ID` = user_role.`RID`
          LEFT OUTER JOIN USER
            ON user.id = user_role.`UID`
    </select>
</mapper>

2.1.5 编写了role的测试类

public class roleTest {

    private InputStream in;
    private SqlSession session;
    private RoleDao roleDao;

    @Before  //在执行测试方法前进行执行
    public void init(){
        try {
            //1.读取配置文件获取字节输入流
            in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.获取SqlSessionFactor工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory build = builder.build(in);
            session = build.openSession();    //如果没openSession(true) :则是自动提交
            //3.获取代理对象
            roleDao =  session.getMapper(RoleDao.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @After //在执行测试方法后进行执行
    public void destroy(){

        //事务的提交
        session.commit();
        //5.释放资源
        session.close();
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 测试查询所有的role信息
     */
    @Test
    public void findAllTest(){
        List<Role> allAccount = roleDao.findAll();
        for (Role account : allAccount) {
            System.out.println("-------每一个user的信息-----------");
            System.out.println(account);
            System.out.println(account.getUsers());
        }
    }
}

运行结果图:
注意比对在mysql中的查询结果是否相同
记录Kite的学习历程之 Mybatis多表查询_第9张图片

上面就是今天大概的学习类内容了
几天还换了idea的背景图
记录Kite的学习历程之 Mybatis多表查询_第10张图片
有点想我的老大了 初中的最爱,RIP

2020/6/11/21:18 去洗澡了 加油偶

你可能感兴趣的:(每天的学习笔记,java,mybatis,mysql,数据库)