博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
07 Mybatis的多表查询1----1对多和多对1
阅读量:4325 次
发布时间:2019-06-06

本文共 10236 字,大约阅读时间需要 34 分钟。

1.表与表之间的关系及其举例

表之间的关系有4种:一对多、多对一、一对一、多对多。

举例:
  (1)用户和订单就是一对多

    一个用户可以下多个订单

  (2)订单和用户就是多对一
    多个订单属于同一个用户

  (3)人和身份证号就是一对一

    一个人只能有一个身份证号
    一个身份证号只能属于一个人

  (4)老师和学生之间就是多对多

    一个学生可以被多个老师教过
    一个老师可以交多个学生

2.mybatis中的多表查询

示例:用户和账户
  一个用户可以有多个账户
  一个账户只能属于一个用户(多个账户也可以属于同一个用户)
步骤:
  1、建立两张表:用户表,账户表
    让用户表和账户表之间具备一对多的关系:需要使用外键在账户表中添加
  2、建立两个实体类:用户实体类和账户实体类
    让用户和账户的实体类能体现出来一对多的关系
  3、建立两个配置文件
    用户的配置文件
    账户的配置文件
  4、实现配置:
    当我们查询用户时,可以同时得到用户下所包含的账户信息
    当我们查询账户时,可以同时得到账户的所属用户信息

3.操作案例

(1)案例1

查询所有查询所有账户,及其用户名和地址信息(逻辑为:账户表account-----》用户信息表user)

<1>对数据库表Account对应的实体类Account.java进行改造,加入User对象作为成员变量

package domain;import java.io.Serializable;/** * 数据库的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 +                '}';    }}

<2>IAccountDao中添加findAll()方法

package dao;import domain.Account;import domain.AccountUser;import java.util.List;public interface IAccountDao {    /**     * 查询所有查询所有账户,及其用户名和地址信息     * @return     */    List
findAll(); }

<3>映射关系配置

(1)IAccountDao.xml配置

ResultMap标签基本作用:建立SQL查询结果字段与实体属性的映射关系信息

标签属性id和type的含义:

  id:该resultMap的标志

  type:返回值的类名

子标签含义:

  id:用于设置主键字段与领域模型属性的映射关系,此处主键为ID,对应id。

  result:用于设置普通字段与领域模型属性的映射关系
  association 为关联关系,是实现一对一的关键
    1. property 为javabean中容器对应字段名     
    2. javaType 指定关联的类型,当使用select属性时,无需指定关联的类型
    3. select 使用另一个select查询封装的结果
    4. column 为数据库中的列名,与select配合使用

 

注解配置:IAccountDao.java文件中进行如下配置

/**     * 查询所有查询所有账户,及其用户名和地址信息     * 注解中的第四个result的column为uid(外键),连接到user表,select调用dao.IUserDao.findById()方法     * @return     */    @Select("select * from account")    @Results(id="accountMap",value = {            @Result(id=true,column = "id",property = "id"),            @Result(column = "uid",property = "uid"),            @Result(column = "money",property = "money"),            @Result(column = "uid",property = "user",one=@One(select = "dao.IUserDao.findById",fetchType = FetchType.EAGER))    })    List
findAll();

<4>测试代码

package test;import dao.IAccountDao;import dao.IUserDao;import domain.Account;import domain.AccountUser;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.Test;import java.io.InputStream;import java.util.List;public class MybatisTest01 {    private InputStream in;    private SqlSession sqlSession;    private IAccountDao accountDao;    /**     * 初始化MyBatis     * @throws Exception     */    public void initMyBatis() throws Exception{        //1.读取配置文件        in = Resources.getResourceAsStream("SqlMapConfig.xml");        //2.创建SqlSessionFactory        SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder(); //创建SqlSessionFactory的构建者builder        SqlSessionFactory factory=builder.build(in);  //利用构建者builder创建SqlSessionFactory        //3.使用工厂生产SqlSession对象        sqlSession = factory.openSession();        //4.使用SqlSessions对象创建Dao接口的代理对象        accountDao = sqlSession.getMapper(IAccountDao.class);    }    /**     * 释放资源     * @throws Exception     */    public void destroy() throws Exception{        sqlSession.commit();//提交事务        sqlSession.close();        in.close();    }    /**     * 查询所有     * @throws Exception     */    @Test    public void testFindAll()throws Exception{        initMyBatis();        List
accounts = accountDao.findAll(); for (Account account : accounts) { System.out.println(account); System.out.println(account.getUser()); } destroy(); } }

效果图:

 

(2)案例2

查询所有查询用户信息,及其拥有的账户信息(逻辑为:用户信息表user-----》账户表account)

<1>对数据库表user对应的实体类User.java进行改造,加入List<Account>作为成员变量

package domain;import java.io.Serializable;import java.util.Date;import java.util.List;/** * 数据库表对应的实体类 */public class User implements Serializable {    //实体类的成员变量名称应该与数据库中的列名一致    private Integer id;    private String username;    private Date birthday;    private String sex;    private String address;    private List
accounts; public List
getAccounts() { return accounts; } public void setAccounts(List
accounts) { this.accounts = accounts; } 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; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", birthday=" + birthday + ", sex='" + sex + '\'' + ", address='" + address + '\'' + '}'; }}

<2>IUserDao中添加findAll()方法

package dao;import domain.User;import java.util.List;/** * */public interface IUserDao {    /**     * 查询所有     * @return     */    List
findAll();}

<3>IUserDao.xml

ResultMap标签基本作用:建立SQL查询结果字段与实体属性的映射关系信息

标签属性id和type的含义:

  id:该resultMap的标志

  type:返回值的类名

子标签含义:

  id:用于设置主键字段与领域模型属性的映射关系,此处主键为ID,对应id。

  result:用于设置普通字段与领域模型属性的映射关系
  association 为关联关系,是实现一对一的关键 
    1. property 为javabean中容器对应字段名     
    2. javaType 指定关联的类型,当使用select属性时,无需指定关联的类型
    3. select 使用另一个select查询封装的结果
    4. column 为数据库中的列名

  collection 为关联关系,是实现一对多的关键

    1. property 为javabean中容器对应字段名
    2. ofType 指定集合中元素的对象类型
    3. select 使用另一个查询封装的结果
    4. column 为数据库中的列名,与select配合使用

注解配置:IUserDao.java文件中进行如下配置

/**     * 查询所有     * @return     */    @Select("select * from user")    @Results(id="userMap",value = {            @Result(id=true,column = "id",property = "id"),            @Result(column = "username",property = "username"),            @Result(column = "address",property = "address"),            @Result(column = "sex",property = "sex"),            @Result(column = "birthday",property = "birthday"),            @Result(column = "id",property ="accounts",many =@Many(select = "dao.IAccountDao.findAccountById",fetchType = FetchType.EAGER))    })    List
findAll();

<4>测试代码

package test;import dao.IAccountDao;import dao.IUserDao;import domain.Account;import domain.AccountUser;import 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.Test;import java.io.InputStream;import java.util.List;public class MybatisTest02_User {    private InputStream in;    private SqlSession sqlSession;    private IUserDao userDao;    /**     * 初始化MyBatis     * @throws Exception     */    public void initMyBatis() throws Exception{        //1.读取配置文件        in = Resources.getResourceAsStream("SqlMapConfig.xml");        //2.创建SqlSessionFactory        SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder(); //创建SqlSessionFactory的构建者builder        SqlSessionFactory factory=builder.build(in);  //利用构建者builder创建SqlSessionFactory        //3.使用工厂生产SqlSession对象        sqlSession = factory.openSession();        //4.使用SqlSessions对象创建Dao接口的代理对象        userDao = sqlSession.getMapper(IUserDao.class);    }    /**     * 释放资源     * @throws Exception     */    public void destroy() throws Exception{        sqlSession.commit();//提交事务        sqlSession.close();        in.close();    }    /**     * 查询所有     * @throws Exception     */    @Test    public void testFindAll()throws Exception{        initMyBatis();        List
users = userDao.findAll(); for (User user : users) { System.out.println(user); System.out.println(user.getAccounts()); } destroy(); }}

效果图:

4.Mybatis中的缓存

(1)什么是缓存
  存在于内存中的临时数据。
(2)为什么使用缓存
  减少和数据库的交互次数,提高执行效率。
(3)什么样的数据能使用缓存,什么样的数据不能使用
  <1>适用于缓存:
    经常查询并且不经常改变的。
    数据的正确与否对最终结果影响不大的。
  <2>不适用于缓存:
    经常改变的数据
    数据的正确与否对最终结果影响很大的。
    例如:商品的库存,银行的汇率,股市的牌价。
5.Mybatis中的一级缓存和二级缓存
(1)一级缓存:
  它指的是Mybatis中SqlSession对象的缓存。
  当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供一块区域中。
  该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去sqlsession中
  查询是否有,有的话直接拿出来用。
  当SqlSession对象消失时,mybatis的一级缓存也就消失了。
(2)二级缓存:
  它指的是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。
  二级缓存的使用步骤:
    第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
    第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
    第三步:让当前的操作支持二级缓存(在select标签中配置)

转载于:https://www.cnblogs.com/luckyplj/p/11307874.html

你可能感兴趣的文章
小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_3-2.使用Mybatis注解开发视频列表增删改查...
查看>>
小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-2.微信扫一扫功能开发前期准备...
查看>>
小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_3-3.Vidoe相关接口完善和规范协议...
查看>>
小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-3.微信Oauth2.0交互流程讲解...
查看>>
小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_3-5.PageHelper分页插件使用
查看>>
小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-6.微信扫码登录回调本地域名映射工具Ngrock...
查看>>
小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_4-2.微服务下登录检验解决方案 JWT讲解...
查看>>
小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-8.用户模块开发之保存微信用户信息...
查看>>
HDU 5353 Average
查看>>
进程和计划管理
查看>>
MQ_ActiveMQ环境部署+C#推送和接收消息
查看>>
Ubuntu16.04上使用Anaconda3的Python3.6的pip安装UWSGI报错解决办法
查看>>
学习笔记11.6
查看>>
高效中的细节注意
查看>>
MySQL 之 库操作
查看>>
Python 最抢手、Java 最流行,前线程序员揭秘 2019 软件开发现状
查看>>
R语言(一)
查看>>
商品搜索引擎---分词(插件介绍与入门实例)
查看>>
win7下硬盘安装Windows
查看>>
SQL Server 数据库性能优化(转载)
查看>>