• Mybatis 简介(一)


    这里使用的是3.5.11版本

    MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

    1、持久层框架对比

    - JDBC
        - SQL 夹杂在Java代码中耦合度高,导致硬编码内伤
        - 维护不易且实际开发需求中 SQL 有变化,频繁修改的情况多见
        - 代码冗长,开发效率低
    - Hibernate 和 JPA
        - 操作简便,开发效率高
        - 程序中的长难复杂 SQL 需要绕过框架
        - 内部自动生成的 SQL,不容易做特殊优化
        - 基于全映射的全自动框架,大量字段的 POJO 进行部分映射时比较困难。
        - 反射操作太多,导致数据库性能下降
    - MyBatis
        - 轻量级,性能出色
        - SQL 和 Java 编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据
        - 开发效率稍逊于 Hibernate,但是完全能够接收

    开发效率:Hibernate>Mybatis>JDBC

    运行效率:JDBC>Mybatis>Hibernate

    封装越多,运行效率越慢

    2、快速入门(案例)

    有一个mybitas数据库,使用Mybaits框架来使用id查询数据。

    之前Dao时我们都是创建一个Dao接口,然后自己实现该接口,将sql语句等都写在类里。

    使用Mybstis之后,我们只用写一个xxxMapper接口,之后编写xxxMapper.xml配置信息,在xml文件中编写sql语句,之后再编写一个mabatis-config.xml配置文件(配置数据库信息,以及我们mapper接口的位置),最后使用mybatisapi来进行数据库操作即可。

    步骤①导入依赖


     
     
          org.mybatis
          mybatis
          3.5.11
     

     
     
          mysql
          mysql-connector-java
          8.0.25
     

     
     
          org.junit.jupiter
          junit-jupiter-api
          5.3.1
     

    ②.准备实体类

    public class Employee {

        private Integer empId;

        private String empName;

        private Double empSalary;
        
        //getter | setter
    }

    ③准备mapper接口以及mapperxml文件

    MyBatis 框架下,SQL语句编写位置发生改变,从原来的Java类,改成**XML**或者注解定义!

    推荐在XML文件中编写SQL语句,让用户能更专注于 SQL 代码,不用关注其他的JDBC代码。

    如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码!!

    一般编写SQL语句的文件命名:XxxMapper.xml  Xxx一般取表名!!

    Mybatis 中的 Mapper 接口相当于以前的 Dao。但是区别在于,Mapper 仅仅只是建接口即可,我们不需要提供实现类,具体的SQL写到对应的Mapper文件,该用法的思路如下图所示:

    a.定义mapper接口

    package com.cky.impl;
    
    import com.cky.pojo.Employee;
    
    public interface Mymapper {
       Employee queryByid(int id);
    }
    

    b.定义mapperxml文件

    位置resources/mapper/Mymapper.xml 

    
    
    
    
    
        
        
    

    **注意:**
      - 方法名和SQL的id一致
      - 方法返回值和resultType一致
      - 方法的参数和SQL的参数一致
      - 接口的全类名和映射配置文件的名称空间一致 

    ④准备Mybatis配置文件

    在Resource文件下

    mybatis框架配置文件: 数据库连接信息,性能配置,mapper.xml配置等!

    习惯上命名为 mybatis-config.xml,这个文件名仅仅只是建议,并非强制要求。将来整合 Spring 之后,这个配置文件可以省略,所以大家操作时可以直接复制、粘贴。

    
    
    
    
        
        
            
            
                
                
                
                
                    
                    
                    
                    
                    
                
            
        
    
        
            
            
            
            
            
        
    
    

    ⑤测试

    import com.cky.impl.Mymapper;
    import com.cky.pojo.Employee;
    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.jupiter.api.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    public class Mybatis_test {
        /**
         * projectName: com.atguigu.test
         *
         * description: 测试类
         */
    
            @Test
            public void testSelectEmployee() throws IOException {
    
                // 1.创建SqlSessionFactory对象
                // ①声明Mybatis全局配置文件的路径
                String mybatisConfigFilePath = "mybatis-config.xml";
    
                // ②以输入流的形式加载Mybatis配置文件
                InputStream inputStream = Resources.getResourceAsStream(mybatisConfigFilePath);
    
                // ③基于读取Mybatis配置文件的输入流创建SqlSessionFactory对象
                SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
                // 2.使用SqlSessionFactory对象开启一个会话
                SqlSession session = sessionFactory.openSession();
    
                // 3.根据EmployeeMapper接口的Class对象获取Mapper接口类型的对象(动态代理技术)
    //使用的是jdk动态代理,底层仍然调用的是ibtsa的对应的方法。
    //动态代理将namespce与方法名连接,之后将参数整合到一起。
                Mymapper employeeMapper = session.getMapper(Mymapper.class);
    
                // 4. 调用代理类方法既可以触发对应的SQL语句
                Employee employee = employeeMapper.queryByid(1);
    
                System.out.println("employee = " + employee);
    
                // 4.关闭SqlSession
                session.commit(); //提交事务 [DQL不需要,其他需要]
                session.close(); //关闭会话
    
            }
        }
    

    注意:Mapper接口的抽象方法不能重载!!! 

    3、Mybatis基本使用

    3.1 向sql语句传参

     3.1.1 打开日志输出配置

    通过日志输出配置,我们可以看到接下来我们要讲解的#{}和${}接收参数的区别。

    mybatis配置文件中添加日志配置

    日志配置:


     
     

    3.1.2 #{} 接收参数

    Mybatis会将SQL语句中的#{}转换为问号占位符。占位符+赋值

    3.1.3 ${} 接收参数

    直接赋值,字符串直接拼接

    注意:

    通常不会采用${}的方式传值,为了防止注入攻击。一个特定的适用场景是:通过Java程序动态生成数据库表,表名部分需要Java程序通过参数传入;而JDBC对于表名部分是不能使用问号占位符的,此时只能使用

    结论:实际开发中,能用#{}实现的,肯定不用${}。

    特殊情况: 动态的不是值,是列名或者关键字或者表名,需要使用${}拼接

    3.2 传入参数类型

    这里数据输入具体是指上层方法(例如Service方法)调用Mapper接口时,数据传入的形式。

    - 简单类型:只包含一个值的数据类型
        - 基本数据类型:int、byte、short、double、……
        - 基本数据类型的包装类型:Integer、Character、Double、……
        - 字符串类型:String
    - 复杂类型:包含多个值的数据类型
        - 实体类类型:Employee、Department、……
        - 集合类型:List、Set、Map、……
        - 数组类型:int[]、String[]、……
        - 复合类型:List、实体类中包含集合……

    根据不同的传入类型,我们有不同的规则

    3.2.1 传入单个简单类型

    mapper接口中抽象方法声明;

    Employee selectEmployee(Integer empId);

    mapperxml文件中sql语句

     

    这里我们只需要传入一个简单的基本数据类型即可,因为参数只有一个,单个简单类型参数,

    在#{}中可以随意命名,但是没有必要。通常还是使用和接口方法参数同名。

    3.2.2 传入一个实体参数类型

    mapper接口抽象类定义

    int insertEmployee(Employee employee);

    mapperxmlSQL语句


      insert into t_emp(emp_name,emp_salary) values(#{empName},#{empSalary})
     

     对于实体类,我们需要传入的参数要与实体类对象的变量名相同,不能乱写。

    3.2.3多个简单数据类型

    mapper接口抽象方法

    Employee querybyidandname(Integer id,String name);

    mapperxmlSQL编写

    //不可以随便写 也不能按照抽象方法中的参数名来取
    //方法1 mybatis默认机制 参数默认从arg0...argx 开始
    //方法2 @Param注解 写在接口的抽象方法中
    

     此时类方法这样写

    Employee querybyidandname(@Param("a") Integer id, @Param("b") String name);

    SQL语句这样写

    3.2.4 Map参数数据类型

    mapper接口方法

    Employee querybyidandname(Map data);

    Sql语句

     传入的是Map时,sql语句中接收根据我们传入map的参数名的key就可以.

    3.3 输出数据类型

    对于增删改 一般都只返回影响行数 用int或者long 接收即可。

    但是对于查询,返回的类型就多种多样,那么sql语句的ResultType如何编写呢?

    3.3.1 单个简单输出类型

    ResultType 写法

     1、如果返回的是我们的实体类,直接写类的全限定符即可

    2、别名简称

      java为我们提供了72中基本数据类型的简称

    基本上可以分为:

     ①基本数据类型   int  double->_int _double

     ②包装数据类型  Integer Double ->int double

     ③基本组合数据类型  Map List->小写即可

    3、自定义数据类型

      如何为我们自己的类自定义别名呢?可以在Mybatis配置文件中配置

    官网别名解释

    ①挨个类配置

    
      
      
      
      
      
      
    

     ②批量给包下的类给别名,别名就是类的首字母小写

    
      
    

    如果在批量给别名之后,我们仍想给某些类自己配置别名的话怎么办呢?

    可以在类名上添加@Alias注解,注意该注解必须与批量给别名一起使用,否则不生效

    @Alias("author")
    public class Author {
        ...
    }

    3.3.2 单个实体类型输出

    对于ResultType 我们可以①使用类的全限定符 ②起别名使用别名

    注意:这里有个默认要求:

    我们数据库的列名必须等于属性名 但是如果我们都配置别名的话,比如下方,就会比较麻烦。

    这里,mybatis有个设置,开启该该驼峰式映射设置之后,框架会自动给我们起别名

    但是规则是去掉数据库列名下划线,将下划线后的首字母变大写

    比如 数据库列名 emp_id 会自动帮我们映射为 empId

    如何开启驼峰式映射呢?

    在settings中编写


     
     
     
     
     
     

    3.3.3 返回map类型

    如果返回的是实体类型,则ResultType直接写相应的实体类全限定符或者我们定义过的简写就行。

    但是如果返回的不是实体类型呢?

    我们可以用Map接收。

    mapper接口抽象类方法

    //根据id来查找姓名和工资,返回的不是一个实体类,我们可以用map来接收
    Map querybyid(Integer id);

    mapperXML文件

    3.3.4 返回集合类型

    有时候,我们查找返回的是多条信息,这时候我们返回值类型就是一个集合类型

    mapper接口

    //返回的是一个集合
    List queryByname(String name);

    mapperXML文件

     这里需要注意:

    我们resultType接收的是集合的泛型,而不需要写list

    3.3.5 主键回显

    a.对于自增长类型主键

    int insertnew(Employee employee);
    
            insert into t_emp(emp_name,emp_salary) values(#{empName},#{empSalary})
    
    
    
    keyColumn 表示我们在数据库中的列名

    如果我们不指定这三个值,之后我们便不会将id 赋给该实体的empId属性,我们就不到该值。

    测试:

    import com.cky.impl.Mymapper;
    import com.cky.pojo.Employee;
    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.jupiter.api.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    import java.util.Map;
    
    public class Mybatis_test {
        /**
         * projectName: com.atguigu.test
         *
         * description: 测试类
         */
    
            @Test
            public void testSelectEmployee() throws IOException {
    
                // 1.创建SqlSessionFactory对象
                // ①声明Mybatis全局配置文件的路径
                String mybatisConfigFilePath = "mybatis-config.xml";
    
                // ②以输入流的形式加载Mybatis配置文件
                InputStream inputStream = Resources.getResourceAsStream(mybatisConfigFilePath);
    
                // ③基于读取Mybatis配置文件的输入流创建SqlSessionFactory对象
                SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
               Employee employee1=new Employee();
               employee1.setEmpName("cui");
               employee1.setEmpSalary(20000.0);
                // 2.使用SqlSessionFactory对象开启一个会话
                SqlSession session = sessionFactory.openSession();
    
                // 3.根据EmployeeMapper接口的Class对象获取Mapper接口类型的对象(动态代理技术)
                Mymapper employeeMapper = session.getMapper(Mymapper.class);
    
                // 4. 调用代理类方法既可以触发对应的SQL语句
                int rows = employeeMapper.insertnew(employee1);
            System.out.println(employee1.getEmpId());
                System.out.println("rows = " +rows );
    
                // 4.关闭SqlSession
                session.commit(); //提交事务 [DQL不需要,其他需要]
                session.close(); //关闭会话
    
            }
        }
    

    结果:

     

    如果没有配置那三个参数,我们将获得null

    注意:我们也可以在 这句代码里自动开启提交事务,填写ture表示开启,默认为false

     SqlSession session = sessionFactory.openSession(true);

    b.对于非自增长主键

    而对于不支持自增型主键的数据库(例如 Oracle)或者字符串类型主键,则可以使用 selectKey 子元素:selectKey 元素将会首先运行,id 会被设置,然后插入语句会被调用!

    使用 `selectKey` 帮助插入UUID作为字符串类型主键示例:

    
    
    
    
    
        
        SELECT REPLACE(UUID(),'-','');
        insert into teacher(t_id,t_name) values(#{tID},#{tName})
    
    
    

     通过 `keyProperty` 属性来指定查询到的 UUID 赋值给对象中的 `id` 属性,而 `resultType` 属性指定了 UUID 的类型为 `java.lang.String`。

    order 有两个选值 BEFORE|AFTER 

    before 表示在insert语句执行之前执行 selectkey 反之表示在之后执行。这里生成id,并把id配置给Teacher 属性,肯定是在之前执行。

    通过这种方式,我们不必在自己维护给Teacher对象添加id属性,而是通过mybitas来维护生成id。

    使用这种方式,我们可以方便地插入 UUID 作为字符串类型主键。当然,还有其他插入方式可以使用,如使用Java代码生成UUID并在类中显式设置值等。需要根据具体应用场景和需求选择合适的插入方式。  Java代码自己生成UUID来显示设置如下:

            //自己维护主键
    //        String id= UUID.randomUUID().toString().replaceAll("-","");
            Teacher teacher=new Teacher();
            tearucher.settName("hhh");
    
    //     teacher.settID(id);

    3.3.6 当列名和属性名不一致时

    (1)起别名

      我们可以在sql语句中为 列名起别名 别名与哦我们的属性名一致即可

    (2)开启驼峰式映射


     
     

     

    (3)使用resultMap自定义映射

    resultType与resultMap 二选一

    resultType按照规则自动映射,如果开启了驼峰式映射,会自动映射属性名和列名,但是只能单层映射。多表查询时就无法映射。

    resultMap自定义映射关系,可以深层次可以单层次。 

    
    
    
      
      
      
    
      
      
    
      
    
    
    
    
    resultMap=“id标识”
    
    
  • 相关阅读:
    Linux Redis 源码安装
    QT学习_15_线程间通信以及注意事项
    服务器被入侵怎么办
    Qt中事件的处理
    MySQL之视图,存储
    阿里拆成1+6+N,中台还搞不搞了?
    SaaSBase:什么是数云麒麟CRM?
    弘扬企业家精神!闪马智能创始人兼CEO彭垚再获殊荣
    Linux03: shell编程
    鱼哥赠书活动第②期:《AWD特训营:技术解析、赛题实战与竞赛技巧》《ATT&CK视角下的红蓝对抗实战指南》《智能汽车网络安全权威指南》上下册
  • 原文地址:https://blog.csdn.net/qq_45906101/article/details/133982461