MyBatis_ 进阶_知识整理

MyBatis 进阶

MyBatis 接口代理方式实现 Dao 层
接口代理方式-实现规则
    传统方式实现 Dao 层,我们既要写接口,还要写实现类。而 MyBatis 框架可以帮助我们省略编写 Dao 层接口实现类的步骤。程序员只需要编写接口,由 MyBatis 框架根据接口的定义来创建该接口的动态代理对象。
    
   实现规则
    
    1. 映射配置文件中的名称空间必须和 Dao 层接口的全类名相同。
    2. 映射配置文件中的增删改查标签的 id 属性必须和 Dao 层接口的方法名相同。
    3. 映射配置文件中的增删改查标签的 parameterType 属性必须和 Dao 层接口方法的参数相同。
    4. 映射配置文件中的增删改查标签的 resultType 属性必须和 Dao 层接口方法的返回值相同。 

接口代理方式-代码实现

  1. 删除 mapper 层接口的实现类
  2. 修改映射配置文件
    <mapper namespace="StudentMapper">
    修改 映射配置文件中的名称空间必须和 Dao 层接口的全类名相同
    <mapper namespace="com.itheima.mapper.StudentMapper">
   //此处为dao层接口的全类名            

3.修改 service 层接口的实现类,采用接口代理方式实现功能

实现查询功能一

public List<Student> selectAll() {
        List<Student> list = null;
        SqlSession sqlSession = null;
        InputStream is = null;
        try {
            //1.加载核心配置文件
            is = Resources.getResourceAsStream("MyBatisConfig.xml");

            //2.获取SqlSession工厂对象
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            //3.通过工厂对象获取SqlSession对象
            sqlSession = sqlSessionFactory.openSession(true);

           //4.获取StudentMapper接口的实现类对象
           StudentMapper studentMapper =      sqlSession.getMapper(StudentMapper.class);
    // StudentMapper mapper = new StudentMapperImpl();

            //5.通过实现类对象调用方法,接收结果
            list = studentMapper.selectAll();

        } catch (Exception e) {

        } finally {
            //6.释放资源
            if (sqlSession != null) {
                sqlSession.close();
            }
            if (is != null) {
               try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //7.返回结果
        return list;
    }

由于我们只需执行的只有sql语句,其余代码重复,需要进一步简化

//业务层实现类
    //1.修改StudentMapper 满足接口代理规范(namespace 修改为接口权限定类名,id为方法名)
    //2.到service中使用接口代理
    // 2.1 通过SQLSession在构造方法初始化StudentMapper(或者使用静态代码块初始化StudentMapper)
    // 2.2 实现具体业务方法
    private StudentMapper studentMapper;

    public StudentServiceImpl() {
        SqlSession sqlSession = null;
        InputStream is = null;
        try{
            //1.加载核心配置文件
            is = Resources.getResourceAsStream("MyBatisConfig.xml");
            //2.获取SqlSession工厂对象
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
            //3.通过工厂对象获取SqlSession对象
            sqlSession = sqlSessionFactory.openSession(true);
             //获取动态代理对象
            studentMapper = sqlSession.getMapper(StudentMapper.class);

        }catch (Exception e) {
          
        }
    }
//简化后的方法
 public List<Student> selectAll() {
      return studentMapper.selectAll();
 }

public Student selectById(Integer id) {
    return studentMapper.selectById(id);}
...

接口代理

分析动态代理对象如何生成的
    通过动态代理开发模式,我们只编写一个接口,不写实现类,我们通过 getMapper() 方法最终获取到org.apache.ibatis.binding.MapperProxy 代理对象,然后执行功能,而这个代理对象正是 MyBatis 使用了JDK 的动态代理技术,帮助我们生成了代理实现类对象。从而可以进行相关持久化操作
   分析方法是如何执行的?
   动态代理实现类对象在执行方法的时候最终调用了 mapperMethod.execute() 方法,这个方法中通过 switch 语句根据操作类型来判断是新增、修改、删除、查询操作,最后一步回到了 MyBatis 最原生的SqlSession 方式来执行增删改查 

小结

接口代理方式可以让我们只编写接口即可,而实现类对象由 MyBatis 生成
     实现规则
    1. 映射配置文件中的名称空间必须和 Dao 层接口的全类名相同。
    2. 映射配置文件中的增删改查标签的 id 属性必须和 Dao 层接口的方法名相同。
    3. 映射配置文件中的增删改查标签的 parameterType 属性必须和 Dao 层接口方法的参数相同。
    4. 映射配置文件中的增删改查标签的 resultType 属性必须和 Dao 层接口方法的返回值相同
    
    获取动态代理对象
    SqlSession 功能类中的 getMapper() 方法

动态SQL

MyBatis 映射配置文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL 就是动态变化的,此时在前面学习的 SQL 就不能满足要求了

: 多条件查询
    SELECT  *  FROM student WHERE id = ? AND name = ? AND age = ?
    SELECT  *  FROM student WHERE id = ? AND name = ?
动态 SQL 标签
<if>:条件判断标签
    
   <where>:条件标签。如果有动态条件,则使用该标签代替 where 关键字
    //功能 自动生成where关键字 ,自动去掉多余的and,不会自动添加and
    
 <where>   
    <if test=“条件判断”>
    查询条件拼接
    </if>
        
    <if test=“条件判断”>
      AND 查询条件拼接 //从第二条开始
    </if>
       .... 
 <where/>
        
     
 例如:
 <select id="selectCondition" resultType="student" parameterType="student">
          <include refid="select"/>  //sql片段抽取
-- //这行是注释           SELECT * FROM student
        <where>
            <if test="id != null">
                id = #{id}
            </if>
            <if test="name != null">
                AND name = #{name}
            </if>
            <if test="age != null">
                AND age = #{age}
            </if>
        </where>
    </select>
  
        
        
  <foreach>:循环遍历标签  适用于多个参数或者的关系   
      
 <foreach collection=“”open=“”close=“”item=“”separator=“”>
   获取参数
 </foreach>
     
      参数:
collection:参数容器类型,(list-集合,array-数组)。
open:开始的 SQL 语句。
close:结束的 SQL 语句
item:参数变量名。
separator:分隔符。    
      
      例如:查询多个id  查询语句为
      //1    SELECT * FROM student WHERE id IN(1,2,3);
      //2   SELECT * FROM student WHERE id=1 OR id=2 OR id=3;
      <select id="selectByIds" resultType="student" parameterType="list">
        <include refid="select"/>
--  //       SELECT * FROM student
        <where>
            <foreach collection="list" open="id IN (" close=")" item="id" separator=",">
                #{id}
            </foreach>
        </where>
      </select>
                
SQL片段抽取

我们可以将一些重复性的 SQL 语句进行抽取,以达到复用的效果

<sql>:抽取 SQL 语句标签。
    <sql id=“片段唯一标识”>抽取的 SQL 语句</sql>
    //如上述例子中就使用的sql标签
    <sql id="select" >SELECT * FROM student</sql>
    
 <include>:引入 SQL 片段标签。
    <include refid=“片段唯一标识”/>
    //在上述例子中的引用
    <include refid="select"/>
 
扩展: 如sql语句 不再是 select * from 表名,
             而是需要从特定的列搜索时 select 列名,列名.. from 表名 时
 抽取sql语句标签
           <sql id="fields">列名1,列名2,...</sql>      
         
          <include>:引入 SQL 片段标签
          <include refid="fields"/><sql id="fields">id,name,age</sql>
                 
        <select id="selectByName" resultType="student" parameterType="string">
       select  <include refid="fields"/> from student where name = #{name}
       //就是代替 * 
        </select>          
核心配置文件 – 分页插件

介绍

 分页可以将很多条结果进行分页显示
 如果当前在第一页,则没有上一页。如果当前在最后一页,则没有下一页
 需要明确当前是第几页,这一页中显示多少条结果   

分页插件介绍

 PageHelper:第三方分页助手。将复杂的分页操作进行封装,从而让分页功能变得非常简单。
     
  分页插件实现步骤
    导入 jar 包 jsqlparser-3.1.jar 和 pagehelper-5.1.10.jar 并应用在模块中
     
    在核心配置文件中集成分页助手插件 
     注意 要遵循位置顺序 必须匹配 
     (properties?-->settings?-->typeAliases?-->typeHandlers?-->
      objectFactory?-->objectWrapperFactory?-->reflectorFactory?
      -->plugins?-->environments?-->databaseIdProvider?-->mappers?)"。
    <!--集成分页助手插件-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins> 
 shift+shift 全局搜索  
    
PageHelpe
PageHelper:分页助手功能类。
    startPage():设置分页参数
分页插件相关参数

PageInfo:封装分页相关参数的功能类

返回值方法名说明
longgetTotal()获取总条数
intgetPages()获取总页数
intgetPageNum()获取当前页
intgetPageSize()获取每页显示条数
intgetPrePage()获取上一页
intgetNextPage()获取下一页
booleanisIsFirstPage()获取是否是第一页
booleanisIsLastPage()获取是否是最后一页

例如

public void selectPaging() throws Exception{
        //1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");

        //2.获取SqlSession工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

        //3.通过工厂对象获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        //通过分页助手来实现分页功能  PageHelper:分页助手功能类。startPage():设置分页参数
        // 第一页:显示3条数据
        PageHelper.startPage(1,3);
        // 第二页:显示3条数据
        //PageHelper.startPage(2,3);
        // 第三页:显示3条数据
//        PageHelper.startPage(3,3);

        //5.调用实现类的方法,接收结果
        List<Student> list = mapper.selectAll();

        //6.处理结果
        for (Student student : list) {
            System.out.println(student);
        }

        //获取分页相关参数
        PageInfo<Student> info = new PageInfo<>(list);
        System.out.println("总条数:" + info.getTotal());
        System.out.println("总页数:" + info.getPages());
        System.out.println("当前页:" + info.getPageNum());
        System.out.println("每页显示条数:" + info.getPageSize());
        System.out.println("上一页:" + info.getPrePage());
        System.out.println("下一页:" + info.getNextPage());
        System.out.println("是否是第一页:" + info.isIsFirstPage());
        System.out.println("是否是最后一页:" + info.isIsLastPage());

        //7.释放资源
        sqlSession.close();
        is.close();
    }

MyBatis 多表操作

1.一对一
 一对一模型:人和身份证,一个人只有一个身份证
<resultMap>:配置字段和对象属性的映射关系标签。
        id 属性:唯一标识
        type 属性:实体对象类型
     
  <id>:配置主键映射关系标签。
  <result>:配置非主键映射关系标签。
     column 属性:表中字段名称
	 property 属性: 实体对象变量名称
     
     <association>:配置被包含对象的映射关系标签。 //仅用于一对一
        property 属性:被包含对象的变量名
        javaType 属性:被包含对象的数据类型

一对一的配置文件 案例

<?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.itheima.table01.OneToOneMapper">
    <!--配置字段和实体对象属性的映射关系-->
    <resultMap id="oneToOne" type="card">
        <id column="cid" property="id" />
        <result column="number" property="number" />
        <!--
            association:配置被包含对象的映射关系
            property:被包含对象的变量名
            javaType:被包含对象的数据类型
        -->
        <association property="p" javaType="person">  //源于Card类中定义的  private Person p;       //所属人的对象
            <id column="pid" property="id" />
            <result column="name" property="name" />
            <result column="age" property="age" />
        </association>
    </resultMap>
   // 需要配置新的 resultMap 时 在select语句前 否则报错
    <select id="selectAll" resultMap="oneToOne">
        SELECT c.id cid,number,pid,NAME,age FROM card c,person p WHERE c.pid=p.id
    </select>
</mapper>

查询结果

显示列名为 cid number pid name age;

2.一对多
一对多模型:班级和学生,一个班级可以有多个学生
<resultMap>:配置字段和对象属性的映射关系标签。
    id 属性:唯一标识
    type 属性:实体对象类型
     <id>:配置主键映射关系标签。
     <result>:配置非主键映射关系标签。
    column 属性:表中字段名称
    property 属性: 实体对象变量名称
    //不同的地方
   <collection>:配置被包含集合对象的映射关系标签。
    property 属性:被包含集合对象的变量名
    ofType 属性:集合中保存的对象数据类型
    
3.多对多
多对多模型:学生和课程,一个学生可以选择多门课程、一个课程也可以被多个学生所选择
<resultMap>:配置字段和对象属性的映射关系标签。
        id 属性:唯一标识
        type 属性:实体对象类型
     <id>:配置主键映射关系标签。
     <result>:配置非主键映射关系标签。
        column 属性:表中字段名称
        property 属性: 实体对象变量名称
 <collection>:配置被包含集合对象的映射关系标签。
    property 属性:被包含集合对象的变量名
    ofType 属性:集合中保存的对象数据类型

resultmap 代表了方法返回值类型的主体,里面的属性具体映射关系需要手动编写

作用:ResultMap他就是一个方法的返回值的对应映射,等价于ResultType
    ResultMap相当于一个通用返回值类型,具体返回值类型通过type属性指定

ResultType这种返回值类型是纯粹的实体类型

使用环境

ResultType:普通单表查询使用
ResultMap:多表查询时使用    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值