美文网首页
mybatis笔记 - 07

mybatis笔记 - 07

作者: 50ef8076d671 | 来源:发表于2017-07-14 22:20 被阅读0次

2017 06 18

多对一和一对多关系的查询应用

多对一

关联表查询:

提出需求:

以学生和班级为例 :
站在学生的角度上 多对一的关系 N......1
站在班级的角度上 一对多的关系 1......N
因此如果学生和班级分成两张表 需要将两张表进行关系关联
在关系型数据库中可以采取的方式:
    1.逻辑关联:
        并不利用数据库提供的工具对表与表之间进行操作
        程序编写人员在程序内对两个表的内容进行操作 通过代码进行联系的建立
        方便数据迁移 开发使用的第一选择
    2.物理关联:
        利用外键形式进行数据的关联 
        通过这种方式完成多对一的表示   外键永远在多的一方
采取物理关联 需要进行外键设置 如下图:
image
那么 在java当中怎么来表示多对一的关系呢?
同样的逻辑 在 “多” 的一方 建立 “一” 的一方的对象属性
image

现在要查询学生信息并带回班级信息(class_name)

假设给定学生ID(studeny_id)

需要新建ClassInFo.java文件和Student.java文件
新建 Studentmapper.xml  和 ClassInFomapper.xml文件
更改主配置文件 mybatis-config.xml  和  log4j.properties

Studenmapper.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.shxt.model.Student">
    <resultMap type="Student" id="BaseResultMapperStudent">
        <id column="student_id" property="student_id" />
        <result column="student_name" property="student_name" />
        <result column="sex" property="sex" />
    </resultMap>
</mapper>

ClassInFomapper.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.shxt.model.ClassInfo">
    <resultMap type="ClassInfo" id="BaseResultMapperClassInFo">
        <id column="class_id" property="class_id" />
        <result column="class_name" property="class_name" />
    </resultMap>
</mapper>

mybatis-config.xml文件添加mapper映射文件的引用路径

<mappers>
    <mapper resource="com/shxt/model/StudentMapper.xml"/>
    <mapper resource="com/shxt/model/ClassInFoMapper.xml"/>
</mappers>

log4j.properties属性文件内添加sql语句显示所必需的命名空间

log4j.logger.com.shxt.model.Student=TRACE
log4j.logger.com.shxt.model.ClassInFo=TRACE

为了能够保存查询出来的Class的ID 需要在Student.java类中新增一个属性 并在Studentmapper.xml中表明

Student.java :

    private Integer class_id;

    public Integer getClass_id() {
        return this.class_id;
    }
    public void setClass_id( Integer class_id ) {
        this.class_id = class_id;
    }

Studentmapper.xml :

 <resultMap type="Student" id="BaseResultMapperStudent">
        <id column="student_id" property="student_id" />
        <result column="student_name" property="student_name" />
        <result column="sex" property="sex" />
        <result column="class_id" property="class_id" />
</resultMap>

传统方式:

mapper映射文件语句示例:

Studentmapper.xml

<sql id="student_base_columns">
    student_id,student_name,sex,user_name
</sql>
<select id="select01" parameterType="_int" resultMap="BaseResultMapperStudent">
     SELECT
     <include refid="student_base_columns"/>
    FROM
        student
    WHERE
        student_Id=#{student_id}
</select>

ClassInFomapper.xml

<sql id="ClassInFo_base_columns">
    class_id,class_name
</sql>
<select id="get01" parameterType="_int" resultMap="BaseResultMapperClassInFo">
     SELECT
        <include refid="class_base_columns"/>
    FROM
        classinfo
    WHERE
        class_Id=#{class_id}
</select>

测试用例书写:

    @Test
public void tesMethod01(){
    SqlSession sqlsession = null;
    try {
        sqlsession = MyBatisUtils.getSqlSession();
        //首先进行查询  拿到下一步查询必须的class_id
        Student student = sqlsession.selectOne(Student.class.getName()+".select01",1);
        //进行判断   利用class_id进行班级信息的查询
        if(student.getClass_id()!=null){
            ClassInFo classInFo = sqlsession.selectOne(Class.class.getName()+".get01",student.getClass_id());
            //将查询出来的classInFo对象添加到student对象中
            student.setClassInFo(classInFo);
        }
        //调用toString()进行输出
        System.out.println(student);
    } finally {
        MyBatisUtils.closeSqlSession(sqlsession);
    }
}

select方式:

Studentmapper.xml:

<resultMap type="Student" id="BaseResultMapperStudent">
    <id column="student_id" property="student_id" />
    <result column="student_name" property="student_name" />
    <result column="sex" property="sex" />
    <result column="class_id" property="class_id" />
    <association property="calssInFo" javaType="ClassInFo" column="class_id" select="com.shxt.model.ClassInFo.get01"/>
        <!--  <association>     关联对象的标签    property 属性名   javaType  这里因为是自定义类 所以采用别名方式   column建立联系的字段名(关键)  select  去执行哪个命名空间的哪条语句(定位)-->
</resultMap>
 <select id="select01" parameterType="_int" resultMap="BaseResultMapperStudent">
     SELECT
        <include refid="student_base_columns"/>
    FROM
        student
    WHERE
        student_Id=#{student_id}
</select>

测试用例书写:

    @Test
public void tesMethod02(){
    SqlSession sqlsession = null;
    try {
        sqlsession = MyBatisUtils.getSqlSession();
        Student student = sqlsession.selectOne(Student.class.getName()+".select01",1);
        System.out.println(student);
    } finally {
        MyBatisUtils.closeSqlSession(sqlsession);
    }
}
如果编写完成select方式 再用传统方式查询相同sql语句 将会产生三条查询语句(第一次执行之后 会因为缓存原因 log4j显示两条语句)
对此 mybatis提供了<resultMap>标签的继承 使用extends属性 将内置对象与关联对象分离 按照需求 如果需要用到关联对象 就调用集成后的<resultMap>标签

代码示例:
Studentmapper.xml

<resultMap type="Student" id="BaseResultMapperStudent">
    <id column="student_id" property="student_id" />
    <result column="student_name" property="student_name" />
    <result column="sex" property="sex" />
    <result column="class_id" property="class_id" />
</resultMap>

<resultMap type="Student" id="BaseResultMapperStudentByObject" extends="BaseResultMapperStudent">
    <association property="calssInFo" javaType="ClassInFo" column="class_id" select="com.shxt.model.ClassInFo.get01"/>
</resultMap>

连接查询方式:

mapper映射文件添加如下内容:


image
使用左外链接的方式   其实也可以进行两个表的查询,例如
SELECT * FROM class c,teacher t WHERE c.teacher_id=t.t_id AND c.c_id=1;
(这个语句我瞎写的   —— . —— )
image

测试代码示例:

@Test
public void tesMethod03(){
    SqlSession sqlsession = null;
    try {
        sqlsession = MyBatisUtils.getSqlSession();
        Student student = sqlsession.selectOne(Student.class.getName()+".query",1);
        System.out.println(student);
    } finally {
        MyBatisUtils.closeSqlSession(sqlsession);
    }
}

如果想进行多条记录的查询

需要将mapper文件中的where条件子句删掉

在测试用例中使用selectlist方法查询

返回List<Object>类型的值 再进行下一步处理

简单扩展 DTO POJO VO BO PO

同样的实体化类 处在不同的思想和场景下 针对于不同的目的 就有了这些名词的区别

一对多

依然以上述为例

上文介绍站在学生角度看的“多对一”关系的处理

现在尝试站在教室角度 来解决“一对多”关系的处理

在上文中 我们进行的实例化 仅仅是针对于学生和教室来做的

多个学生对象可以对应一个教室对象

我们需要在学生的持久化对象内建立教室对象的id属性 在数据库中建立主键联系 进而运用DTO对象或者select方式 连接查询方式来拿到教室对象的详细内容

现在我们转换思路 将“多对一”转化为“一对多”

首先需要在class持久化对象内建立student对象

但是由于是“一对多”关系 一个class对象会对应多个student对象 我们需要创建一个List<Student>类型的对象来进行查询结果的存储

同样在sudent实体化类中 依然存在 class_id 属性 依然可以进行一对一的查询

可以使用<collection>标签来进行“一对多”关系的查询处理

<resultMap type="ClassInfo" id="simple01" extends="BaseResultMapper">
<!-- collection标签 
    property指代类中属性名   在这里代表类中的studentList集合 
    javaType可以忽略不写让Mybatis来进行自动处理也可简写为list
    ofType在集合中存的是什么类型   
    column指代用哪个字段进行下一步查询
    select用来进行定位下一步动作的命名空间内的sql语句
-->
    <collection property="studentList" javaType="java.util.List" ofType="Student"
     column="class_id"  select="com.shxt.model.Student.select01"/>
</resultMap>

在两个映射文件中的代码如下图所示

重点是<collection>标签的运用

在测试文件中测试用例的书写为一般测试格式
故不予示范


相关文章

  • Spring系列 | 小荷才露尖尖角

    MyBatis学习笔记 MyBatis操练 MyBatis源码 SpringMVC学习笔记 SpringMVC...

  • MyBatis缓存

    MyBatis Mybatis笔记连载上篇连接Mybatis简单操作学习 Mybatis笔记连载下篇连接Mybat...

  • Mybatis动态SQL

    MyBatis Mybatis笔记连载上篇连接MyBatis缓存Mybatis笔记连载下篇连接 动态SQL 动态S...

  • mybatis笔记 - 07

    2017 06 18 多对一和一对多关系的查询应用 多对一 关联表查询: 提出需求: 以学生和班级为例 : 站在学...

  • Mybatis 学习笔记

    Mybatis 学习笔记 配置 MyBatis 环境 导入MyBaits依赖jar包 要使用 MyBatis, 需...

  • Mybatis学习笔记汇总(包括源码和jar包)

    博客整理 Mybatis学习笔记(一)——对原生jdbc中问题的总结 Mybatis学习笔记(二)——Mybati...

  • Mybatis笔记 一

    Mybatis笔记 一 为什么学Mybatis 目前最主流的持久层框架为hibernate与mybatis,而且国...

  • Mybatis--day01

    非本人总结的笔记,抄点笔记复习复习。感谢传智博客及黑马程序猿成长 什么是Mybatis ​ MyBatis 本...

  • 一,MyBatis应用分析与实践

    之前学习MyBatis整理了一些笔记,笔记分为四个部分:1.MyBatis应用分析与实践[https://www....

  • 初识MyBatis

    MyBatis学习笔记(一) 1、什么是MyBatis2、安装3、第一个mybatis实例 前言 1、ORM:Ob...

网友评论

      本文标题:mybatis笔记 - 07

      本文链接:https://www.haomeiwen.com/subject/xfoohxtx.html