JAVA WEB DAY 15_ MyBatis(day03 上)

MyBatis

01-表关系回顾-[★★]

  1. 一对一
      主键是外键:从表的主键和主表的主键形成主外键关系
      外键唯一:从表添加一列作为外键列,引用主表的主键列的值,外键列添加唯一约束。

  2. 一对多
      从表(多方)添加一列作为外键列引用主表(1方)的主键列的值

  3. 多对多
      创建一张中间表,至少有两个字段:分别作为外键引用各种一方的主键,这两个字段一起作为联合主键:共同确定记录的唯一性。

 用户和账号:
   从用户角度:一个用户有多个账号:1对多关系
  从账号角度:一个账号只属于1个用户:1对1关系

  用户和角色:多对多关系
   1个用户可以拥有多个角色
   1个角色可以分配给多个用户

02-多表查询之1对1关系-环境搭建与类设计-[★★]

案例需求

  • 表关系介绍:

    • 一个用户,有多个银行账户。(用户与账户:一对多)

    • 一个账户,只能对应一个人。(账户与用户:一对一)

  • 实现查询一个账户同时关联查询所属用户信息,实现1对1关联查询

环境搭建

  • 准备账号表
DROP TABLE IF EXISTS `USER`;

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL COMMENT '用户名称',
  `birthday` datetime DEFAULT NULL COMMENT '生日',
  `sex` char(1) DEFAULT NULL COMMENT '性别',
  `address` varchar(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=56 DEFAULT CHARSET=utf8;

insert  into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (41,'老王','2018-02-27 17:47:08','男','中山'),(42,'小二王','2018-03-02 15:09:37','女','中山金燕龙'),(45,'中山青软','2018-03-04 12:04:06','男','中山金燕龙'),(46,'老王','2018-03-07 17:37:26','男','中山');

DROP TABLE IF EXISTS account;

CREATE TABLE account (
  accountId int(11) NOT NULL COMMENT '编号',
  UID int(11) default NULL COMMENT '用户编号',
  MONEY double default NULL COMMENT '金额',
  PRIMARY KEY  (accountId),
  KEY FK_Reference_8 (UID),
  CONSTRAINT FK_Reference_8 FOREIGN KEY (UID) REFERENCES user (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert  into account(accountId,UID,MONEY) values (1,46,1000),(2,45,1000),(3,46,2000);
  • 复制项目创建新项目
  • 设计Account类
  • User类已有,不用重新设计
  • Account类:一个账号对应一个用户
package com.pkx.entity;

/**
 * 账户实体类
 * 查询账号信息同时查询该账号对应的用户信息
 */
public class Account {
    private int accountId;
    private int uid;
    private double money;

    // 账号对应的用户:1对1关系
    private User user;

    public Account(int accountId, int uid, double money) {
        this.accountId = accountId;
        this.uid = uid;
        this.money = money;
    }

    public Account() {
    }

    public int getAccountId() {
        return accountId;
    }

    public void setAccountId(int accountId) {
        this.accountId = accountId;
    }

    public int getUid() {
        return uid;
    }

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

    public double getMoney() {
        return money;
    }

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

    public User getUser() {
        return user;
    }

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

    @Override
    public String toString() {
        return "Account{" +
                "accountId=" + accountId +
                ", uid=" + uid +
                ", money=" + money +
                ", user=" + user +
                '}';
    }
}
  • 如何设计账号类实现账号与用户的一对一关联?
    在账号类中添加一个成员变量关联对应的用户:private User user;

03-多表查询之1对1关系-代码实现-[★★★★★]

  1. association标签的作用:用来配置一对一关联查询

  2. association标签常用属性
    property:要映射的属性名
    javaType:映射属性名的类型

  • 需求:实现1对1的多表查询:实现查询账户同时查询所属用户信息。

  • 实现步骤:
    1.在lAccountDao接口中定义查询方法findAll0,多表查询返回List,每个Account包含2个表信息
    2.在lAccountDao.xml映射文件配置对应方法与sql语句
    3.配置返回数据类型resultMap,配置1对1关系缺射【重点】
    4.测类

  • IAccountDao代码

/**
 * 数据访问层接口:对账号表进行增删改查操作
 */
public interface IAccountDao {
    /***
     * 查询所有账号:关联查询每个账号的用户信息
     */
    List<Account> findAll();
}
  • IAccountDao.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.pkx.dao.IAccountDao">

    <!--配置数据表字段与实体类属性的对应关系-->
    <resultMap id="accountResultMap" type="account">
        <!--封装Account表数据-->
        <id column="accountId" property="accountId"></id>
        <result column="uid" property="uid"></result>
        <result column="money" property="money"></result>
        <!--封装User表数据
            association标签的作用:用来封装一对一关联查询的数据
                property属性:关联实体类的属性名
                javaType属性:要映射属性的类型
        -->
        <association property="user"
                     javaType="User">
            <id column="id" property="id"></id>
            <result column="username" property="username"></result>
            <result column="birthday" property="birthday"></result>
            <result column="sex" property="sex"></result>
            <result column="address" property="address"></result>
        </association>
    </resultMap>
    <!--查询所有账号:关联查询每个账号的用户信息-->
    <select id="findAll" resultMap="accountResultMap">
        select * from account a inner join user u on a.`UID` = u.id
    </select>
</mapper>
  • 测试类代码
public class TestAccountDao {

    private static  SqlSessionFactory sqlSessionFactory = null;
    private SqlSession sqlSession = null;

    // 该方法在所有测试方法执行之前执行1次
    @BeforeClass
    public static void init() throws Exception{
        // 1. 获取字节输入流:关联mybatis主配置文件
        InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
        // 2. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 3. 根据字节输入流获取SqlSessionFactory对象
        sqlSessionFactory = builder.build(in);
    }

    // 该方法会在每个测试方法执行之前执行1次
    @Before
    public void before(){
        // 4. 获取SqlSession对象:等价连接对象
        // true:事务自动提交,false:不自动提交,默认值
        sqlSession = sqlSessionFactory.openSession();
    }


    // 在每个测试方法执行之后执行1次
    @After
    public  void after(){
        // 7. 关闭连接释放资源
        sqlSession.close();
    }

    // 查询所有账号:关联查询用户信息
    @Test
    public void testFindAll(){
        // 1. 获得接口实现类对象
        IAccountDao accountDao = sqlSession.getMapper(IAccountDao.class);
        // 2. 查询所有账号
        List<Account> accountList = accountDao.findAll();
        // 3. 遍历输出所有账号
        for (Account account : accountList) {
            System.out.println(account);
        }
    }

}

04-多表查询之1对多关系-代码实现-[★★★★★]

  1. collection标签的作用:用来配置一对多关联查询
  2. collection标签常用属性
    property:要映射的属性名称
    javaType:要映射的属性类型
    ofType:集合中存储对象的类型
  • 需求:掌握1对多关系多表查询:实现查询用户信息同时查询所属账号信息。

  • 实现步骤
    1.设计POJO的User类,增加账户的成是List
    2.在IUserDao接口中增加findAll0查询多表
    3.在UserDao.xml映射文件配置对应方法,配置1对多关系映射【重点】
    4.测试类

  • User类代码

  • 修改 User类,添加成员变量:accountList

/**用户实体类对象 */
public class User {

    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    // 用户的账号列表:
    // 用户与账号的关系:1对多
    private List<Account> accountList;

  • IUserDao接口代码
/**
  数据访问层接口:对用户进行增删改查操作
 */
public interface IUserDao {
    /**
     * 查询所有用户:关联查询每个用户的所有账号信息
     */
    List<User> findAll();
}
  • IUserDao.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.pkx.dao.IUserDao">

    <!--配置一对多的关联查询的映射-->
    <resultMap id="userMap" type="user">
        <!--封装user表数据-->
        <id column="id" property="id"></id>
        <result column="username" property="username"></result>
        <result column="birthday" property="birthday"></result>
        <result column="sex" property="sex"></result>
        <result column="address" property="address"></result>

        <!--collection标签:用来映射一对多关联查询的数据
                property:要映射的属性名
                javaType:要映射属性的类型
                ofType:集合存储的数据类型
        -->
        <collection property="accountList"
                    javaType="list"
                    ofType="account">
            <!--封装account表的数据-->
            <id column="accountId" property="accountId"></id>
            <result column="uid" property="uid"></result>
            <result column="money" property="money"></result>
        </collection>
    </resultMap>
    <!--目标:查询所有用户:关联每个用户的所有账号信息 -->
    <select id="findAll" resultMap="userMap">
        select *
        from user u
        left join account a
        on a.uid = u.id
    </select>
</mapper>
  • 测试代码
// 查询所有用户:关联用户的所有账号
@Test
public void testFindAll(){
    // 1. 获得接口代理对象
    IUserDao userDao = sqlSession.getMapper(IUserDao.class);
    // 2. 查询所有用户
    List<User> userList = userDao.findAll();
    // 3. 遍历所有用户
    for (User user : userList) {
        System.out.println(user);
    }
}

05-多表查询之多对多关系-环境搭建与类设计-[★★]

在多对多关系的实体类中,各自添加一个类型为List的成员变量:存储对方类型的对象。

  • 需求:掌握多对多关系关联表查询
  • 用户与角色, 多对多关系
  • 描述
    • 一个用户,有多个角色
    • 一个角色,有多个用户
  • 实现用户与角色多对多关系多表查询
  • 环境搭建
  • 数据表
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,'校长','管理整个学校');


DROP TABLE IF EXISTS 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;

insert  into user_role(uid,rid) values (41,1),(45,1),(41,2);
  • 设计Role角色类
/**
 * 角色实体类:用来封装角色表的数据
 */
public class Role {
    private int id;
    private String role_name;
    private String role_desc;

    // 用来封装角色对应的所有用户:1对多
    private List<User> userList;

    public Role(int id, String role_name, String role_desc) {
        this.id = id;
        this.role_name = role_name;
        this.role_desc = role_desc;
    }

    public Role() {
    }

    public int getId() {
        return id;
    }

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

    public String getRole_name() {
        return role_name;
    }

    public void setRole_name(String role_name) {
        this.role_name = role_name;
    }

    public String getRole_desc() {
        return role_desc;
    }

    public void setRole_desc(String role_desc) {
        this.role_desc = role_desc;
    }


    public List<User> getUserList() {
        return userList;
    }

    public void setUserList(List<User> userList) {
        this.userList = userList;
    }

    @Override
    public String toString() {
        return "Role{" +
                "id=" + id +
                ", role_name='" + role_name + '\'' +
                ", role_desc='" + role_desc + '\'' +
                ", userList=" + userList +
                '}';
    }
}
  • 设计User类
/**用户实体类对象 */
public class User {

    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    // 用来封装用户对应的角色信息:1个用户可以拥有多个角色
    private List<Role> roleList;

    public User() {
    }

    public User(Integer id, String username, Date birthday, String sex, String address) {
        this.id = id;
        this.username = username;
        this.birthday = birthday;
        this.sex = sex;
        this.address = address;
    }

    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 Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

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

    public List<Role> getRoleList() {
        return roleList;
    }

    public void setRoleList(List<Role> roleList) {
        this.roleList = roleList;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                ", roleList=" + roleList +
                '}';
    }
}

06-多表查询之多对多关系-用户与角色1对多关系配置-[★★★★★]

  • 需求:实现用户与角色1对多关系映射配置
  • 实现步骤:
    1.IUserDao接口中增加findAll()方法
    2.IUserDao.xml映射配置对应方法,重点配置1对多关系映射
    3.测试类
  • IUserDao接口代码
public interface IUserDao {
    /**
     * 查询所有用户:关联查询每个用户的所有账号信息
     */
    List<User> findAll();
}
  • IUserDao.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.pkx.dao.IUserDao">

    <!--设置实体类属性和数据表字段的关系-->
    <resultMap id="userResultMap" type="user">
        <!--封装User表数据-->
        <id column="id" property="id"></id>
        <result column="username" property="username"></result>
        <result column="birthday" property="birthday"></result>
        <result column="sex" property="sex"></result>
        <result column="address" property="address"></result>

        <!--封装Role表数据-->
        <!--1对多数据封装:一个用户对应多个角色-->
        <collection property="roleList" javaType="list" ofType="role">
            <id column="rid" property="id"></id>
            <result column="roleName" property="roleName"></result>
            <result column="roleDesc" property="roleDesc"></result>
        </collection>

    </resultMap>

    <!--查询所有用户:关联查询每个用户的所有账号信息-->
    <select id="findAll" resultMap="userResultMap">
        select r.id rid, r.`role_name` roleName, r.`role_desc` roleDesc ,u.*
        from user u
        inner join user_role ur
        on u.id = ur.`uid`
        inner join role r
        on r.`id` = ur.`rid`
    </select>
</mapper>
  • 测试类代码
    // 查询所有用户:关联查询角色信息
    @Test
    public void testFindAll(){
        // 1. 获得接口实现类对象
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        // 2. 查询所有用户
        List<User> userList = userDao.findAll();
        // 3. 遍历输出所有用户
        for (User user : userList) {
            System.out.println(user);
        }

07-多表查询之多对多关系-角色与用户1对多关系配置-[★★★★★]

  • 需求:实现角色与用户1对多关系映射配置

  • 实现步骤:
    1.IRoleDao接口中增加findAll()方法
    2.IRoleDao.xml映射配置对应方法,重点配置1对多关系映射
    3.测试类

  • IRoleDao接口代码

public interface IRoleDao {
    // 查询所有角色:关联查询角色对应的所有用户信息
    List<Role> findAll();
}
  • IRoleDao.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.pkx.dao.IRoleDao">

    <resultMap id="roleMap" type="role">
        <!--封装role表数据-->
        <id column="rid" property="id"></id>
        <result column="roleName" property="roleName"></result>
        <result column="roleDesc" property="roleDesc"></result>

        <!--封装user表数据
            1个角色对应多个用户:1对多关系,使用collection标签映射
        -->
        <collection property="userList" javaType="list" ofType="user">
            <id column="id" property="id"></id>
            <result column="username" property="username"></result>
            <result column="birthday" property="birthday"></result>
            <result column="sex" property="sex"></result>
            <result column="address" property="address"></result>
        </collection>
    </resultMap>
    <!--  查询所有角色:关联查询角色对应的所有用户信息 -->
    <select id="findAll" resultMap="roleMap">
        select r.id rid,r.role_name roleName , r.role_desc roleDesc ,u.*
        from role r
        left join user_role ur
        on r.id = ur.rid
        left join user u
        on u.id = ur.uid;
    </select>
</mapper>
  • 测试类代码
    // 查询所有用户:关联查询角色信息
    @Test
    public void testFindAll(){
        // 1. 获得接口实现类对象
        IRoleDao roleDao = sqlSession.getMapper(IRoleDao.class);
        // 2. 查询所有角色
        List<Role> roleList = roleDao.findAll();
        // 3. 遍历输出所有角色
        for (Role role : roleList) {
            System.out.println(role);
        }
    }

08-Mybatis延迟加载介绍-[★★]

  • 目标:理解什么是及时加载,什么是延时加载

延迟加载介绍

  • 延迟加载:就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.

  • 延迟加载优点:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

  • 延迟加载缺点:因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。

  • 小结

  1. 什么是延迟加载:需要使用到数据时才执行SQL语句加载数据
  2. 什么是及时加载:立即加载表的数据
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值