• 小黑子—MyBatis:第一章


    一 小黑子对mybatis进行概述

    • 在文献中看到的framework被翻译为框架

    • Java常用框架:

      • SSM三大框架: Spring + SpringMVC + MyBatis
      • SpringBoot
      • SpringCloud等。。。
    • 框架其实就是对通用代码的苗装,提前写好了一堆接口和类,我们可以在做项目的时候直接引入这些接口和类(引入框架),基于这些现有的接口和类进行开发,可以大大提高开发效率.

    • 框架一般都以jar包的形式存在。(jar包中有class文件以及各种配置文件等。)

    • SSM三大框架的学习顺序:MyBatis、Spring、SpringMVC

    MyBatis是一个持久层框架,负责项目开发中的数据访问层(DAO层)

    具体来说,MyBatis提供以下功能和特点,用于实现数据访问层的开发:

    1. SQL映射:MyBatis通过XML配置文件或注解的方式,将SQL语句与Java方法进行映射,实现了对象关系映射(ORM),将数据库操作封装成Java方法调用。

    2. 参数绑定:MyBatis支持将Java对象、基本类型和Map等作为参数传递给SQL语句,实现了方便灵活的参数绑定。

    3. 结果映射:MyBatis可以将查询结果映射为Java对象或基本类型,并支持关联查询和复杂对象图的映射。

    4. 缓存机制:MyBatis提供了一级缓存和二级缓存的支持,能够减少对数据库的频繁访问,提高系统性能。

    5. 插件扩展:MyBatis提供了插件机制,允许开发者编写自定义插件,拦截并修改MyBatis的核心行为,实现功能的扩展和定制。

    总的来说,MyBatis作为一个优秀的持久层框架,主要负责数据访问层的开发,通过SQL映射、参数绑定和结果映射等功能,简化了与数据库的交互,提高了开发效率和代码的可维护性。

    1.1 mybatis三层架构

    在这里插入图片描述

    • 表现层(UI)︰直接跟前端打交互(一是接收前端ajax请求,二是返回json数据给前端)
    • 业务逻辑层(BLL)︰一是处理表现层转发过来的前端请求(也就是具体业务),二是将从持久层获取的数据返回到表现层。
    • 数据访问层(DAL)︰直接操作数据库完成CRUD,并将获得的数据返回到上一层(也就是业务逻辑层)。
    • Java持久层框架
      • Mybatis
      • Hibernate(实现了JPA规范)
      • jOOQ
      • Guzz
      • Spring Data(实现了JPA规范)
      • ActiveJDBC…

    1.1 了解MyBatis

    • MyBatis本质上就是对JDBC的封装,通过MyBatis完成CRUD。
    • MyBatis在三层架构中负责持久层的,属于持久层框架。
    • MyBatis的发展历程:
      • MyBatis本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis。.2013年11月迁移到Gitub,
      • iBATIS一词来源于“internet”和"abatis”的组合,是一个基于Java的持久层框架。iBATS提供的持久层框架包括SQL Maps和Data Access Obijects(DAOs),
    • 打开mybatis代码可以看到它的包结构中包含: ibatis

    MyBatis框架、Spring框架和Spring MVC框架在项目开发中有一些区别,下面是它们的主要区别:

    1. 定位和职责:
      • MyBatis框架:主要用于数据访问层的开发,提供了强大的SQL映射功能,可以将数据库操作封装成Java方法调用。
      • Spring框架:是一个综合性的企业级开发框架,提供了多种功能和特性,包括IoC容器、AOP、事务管理、Web开发等。
      • Spring MVC框架:是Spring框架的一部分,用于开发Web应用程序的MVC模式,负责接收用户请求、处理逻辑和渲染视图。
    2. 使用场景:
      • MyBatis框架:适用于需要编写复杂SQL语句或对数据库操作有较高灵活性要求的项目,如需要进行复杂数据查询、批量操作等。
      • Spring框架:适用于各种企业级应用项目,提供了综合的解决方案,包括依赖注入、面向切面编程、事务管理等。
      • Spring MVC框架:适用于开发基于Web的应用程序,将请求分发给不同的控制器处理,并将处理结果渲染为视图返回给用户。
    3. 功能和特性:
      • MyBatis框架:提供了强大的SQL映射、参数绑定和结果映射功能,可以直接编写和调优SQL语句,对数据库操作的细粒度控制较高。
      • Spring框架:提供了IoC容器、AOP、事务管理、面向切面编程等功能,支持各种应用层面的开发需求,并简化了开发流程。
      • Spring MVC框架:提供了基于MVC的Web开发模式,包括请求处理、URL映射、视图渲染等功能,支持Restful风格的开发。
    4. 整合方式:
      • MyBatis与Spring的整合:通过Spring提供的MyBatis-Spring模块将二者整合在一起,实现配置的统一和依赖注入的管理。
      • Spring与Spring MVC的整合:Spring MVC是Spring框架的一部分,可以直接在Spring框架中使用Spring MVC的功能,无需额外的整合。
      • MyBatis与Spring MVC的整合:可以将MyBatis作为Spring MVC的持久化框架,结合@RequestMapping注解进行数据库操作。

    总的来说,MyBatis框架主要关注数据访问层开发,Spring框架提供了更多的企业级特性和全面的解决方案,而Spring
    MVC框架则专注于Web应用程序的开发。在实际项目中,可以根据需求选择合适的框架及其整合方式,以实现高效、灵活和可维护的应用程序开发

    1.3 ORM思想

    • ORM:对象关系映射
      • O(Object):Java虚拟机中的Java对象。
      • R(Relational):关系型数据库
      • M(Mapping):将Java虚拟机中的Java对象映射到数据库表中一行记录,或是将数据库表中一行记录映射成Java虚拟机中的一个Java对象。

    ORM图示:
    在这里插入图片描述
    MyBatis框架特点:

    • 支持定制化 SQL、存储过程、基本映射以及高级映射
    • 避免了几乎所有的 JDBC 代码中手动设置参数以及获取结果集
    • 支持XML开发,也支持注解式开发。【为了保证sql语句的灵活,所以mybatis大部分是采用XML方式开发。】
    • 将接口和 Java 的 POJOs(Plain Ordinary Java Object,简单普通的Java对象)映射成数据库中的记录
    • 体积小好学:两个jar包,两个XML配置文件。
    • 完全做到sql解耦合。
    • 提供了基本映射标签。
    • 提供了高级映射标签。
    • 提供了XML标签,支持动态SQL的编写。

    二 小黑子的MyBatis入门程序

    会JDBC,MyBatis就可以学
    在这里插入图片描述

    2.1 Mybatis程序的编写

    resources目录:
    放在这个目录当中的,一般都是资源文件,配置文件。直接放到resources目录下的资源,等同于放到了类的根路径下。

    • 步骤1:打包方式:jar(不需要war,因为mybatis封装的是jdbc。)
    <groupId>com.powernodegroupId>
    <artifactId>mybatis-001-introductionartifactId>
    <version>1.0-SNAPSHOTversion>
    <packaging>jarpackaging>
    
    • 1
    • 2
    • 3
    • 4
    • 步骤2:引入依赖(mybatis依赖 + mysql驱动依赖)
    
    <dependency>
      <groupId>org.mybatisgroupId>
      <artifactId>mybatisartifactId>
      <version>3.5.10version>
    dependency>
    
    <dependency>
      <groupId>mysqlgroupId>
      <artifactId>mysql-connector-javaartifactId>
      <version>8.0.30version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 步骤3:编写mybatis核心配置文件:mybatis-config.xml,在resources根目录下新建mybatis-config.xml配置文件

      • 从XNL中构建SqlSessionFactory
        通过官方的这句话,能想到什么呢?
        • 第一:在MyBatis中一定是有一个很重要的对象,这个对象是:SqlsessionFactory对象。
        • 第二:SqlSessionFactory对象的创建需要XML。
    XNL是什么?
    它一定是一个配置文件。
    
    • 1
    • 2
    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/powernode"/> 
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                dataSource>
            environment>
        environments>
        <mappers>
            
            <mapper resource=""/>
        mappers>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    注意:

    • 第一:这个文件名不是必须叫做mybatis-config.xml,可以用其他的名字。只是大家都采用这个名字。
    • 第二,这个文件存放的位置也不是固定的,可以随意,但一般情况下,会放到类的根路径下。
      mybatis-config.xml文件中的配置信息不理解没关系,先把连接数据库的信息修改以下即可。其他的别动。
    • 步骤4:编写XxxxMapper . xml文件在这个配置文件当中编写SQL语句
      在resources根目录下新建CarMapper.xml配置文件
      • 这个文件名也不是固定的,放的位置也不是固定,我们这里给它起个名字,叫做:CarMapper .xml把它暂时放到类的根路径下
    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="car">
        
        <insert id="insertCar">
            insert into t_car
                (id,car_num,brand,guide_price,produce_time,car_type)
            values
                (null,'102','丰田mirai',40.30,'2014-10-05','氢能源')
        insert>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 步骤5:在mybatis-config.xml文件中指定XxxxMapper.xml文件的路径:
    <mapper resource="CarMapper.xml"/>
    
    • 1

    注意:resource属性会自动从类的根路径下开始查找资源。

    • 注意1:sql语句最后结尾可以不写“;”
    • 注意2:CarMapper.xml文件的名字不是固定的。可以使用其它名字。
    • 注意3:CarMapper.xml文件的位置也是随意的。这里选择放在resources根下,相当于放到了类的根路径下。
    • 注意4:将CarMapper.xml文件路径配置到mybatis-config.xml:
    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/powernode"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                dataSource>
            environment>
        environments>
        <mappers>
            
            <mapper resource="CarMapper.xml"/>
        mappers>
    configuration>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 步骤6:编写MyBatisIntroductionTest代码(使用mybatis的类库,编写mybatis程序,连接数据库,做增删改查就行了。)
      在MyBatis当中,负责执行SQL语句的那个对象叫什么?
      • SqlSession
    • SqlSession是专门用来执行SQL语句的,是一个Java程序和数据库之间的一次会话
    • 要想获取SqlSession对象,需要先获取SqlSeesionFactory对象,通过SqlSessionFactory工厂来生产SqlSession对象
    • 怎么获取SqlSessionFactory对象呢?
      • 需要首先获取SqlSessionFactoryBuilder对象
      • 通过SqlSessionFactoryBuilder对象的build方法,来获取一个SqlSessionFactory对象

    mybatis的核心对象包括:

    sqlSessionFactoryBuilder
    sqlSessionFactory
    sqlsession

    sqlSessionFactoryBuilder --> sqlsessionFactory --> sqlSession

    package com.powernode.mybatis.test;
    
    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 java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    public class MyBatisIntroductionTest {
        public static void main(String[] args) throws IOException {
            //1.获取SqlSessionFactoryBuilder对象
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    
            //2.获取SqlSessionFactory对象,通过传入输入流的文件路径在工厂builder.build方法来进行创建
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");//填写mybatis-config.xml文件的路径
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
    
            //3.获取SqlSession对象,通过工厂的openSession方法进行获取
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            //4.执行SQL语句
            int count = sqlSession.insert("car");//放入设置的mapper文件里sql语句的id
            //返回值是影响数控表当中的记录条数
    
            System.out.println("插入了几条记录:" + count);
    
            //5.然后手动提交,因为SqlSession不支持自动提交
            sqlSession.commit();
    
            //6.关闭资源,(只关闭是不会提交的)
            sqlSession.close();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    注意1:默认采用的事务管理器是:JDBC。JDBC事务默认是不提交的,需要手动提交

    2.2 关于程序的小细节

    mybatis中sql语句的结尾;可以省略

    • Resources.getResourceAsStream小技巧:
      以后繁琐遇到resource这个单词,大部分情况下,这种加载资源的方式就是从类的根路径下开始加载的。

      • 优点:采用这种方式,从类路径当中加载资源,项目的移植性很强。项目从windowst移植到Linux,代码不需要修改,因为这个资源文件一直都在类路径当中
    • InputStream is = new FileInputStream("d ::\\mybatis-config.xml");采用这种方式获取也可以

      • 缺点:可移植性太差了,路径定死了,可能会移植到其他的操作系统当中。,导致以上路径无效,还需要修改java代码中的路径,违背了OCP原则

    所以:

    • mybatis核心配置文件的名字,不一定是:mybatis-config.xml。可以是其他的名字
    • mybatis核心配置文件存放的路径,也不一定是再类的根路径下。可以放到其他位置。但是为了项目的可移植性,最好将这个配置文件放到类路径下

    系统类加载器有一个方法叫做:getResourceAsStream它就是从类路径当中加载资源的。
    通过源代码分析发现:

    • InputStream is = Resources.getResourceAsStream( "mybatis-config.xml");

    底层的源代码其实就是:

    • InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");

    CarMapper.xml文件的名字是固定的吗?
    都不是固定的。

    resource属性:这种方式是从类路径当中加载资源。
    url属性:这种方式是从绝对路径当中加载资源。

    2.3 mybatis事务管理机制解析

    在mybatis-config.xml文件中,可以通过以下的配置进行mybatis的事务管理

    • type属性的值包括两个:
      • JDBC(jdbc)
      • MANAGED(managed)
      • type后面的值,只有以上两个值可选,不区分大小写

    在mybatis中提供了两种事务管理:

    • 第一种:JDBC事务管理
    • 第二种:MANAGED事务管理

    JDBC事务管理器:

    • mybatis框架自己管理事务,自己采用元素的JDBC代码去管理事务:
      • conn.setAutoCommit(false);开启事务
      • …业务处理…
      • conn.commit();手动提交事务
    • 使用JDBC事务管理器的话,底层创建的事务管理器对象:jdbctransaction对象
    • 如果编写的代码是下面的代码:
      • SqlSession sqlSession = sqlSessionFactory.openSession(true);
      • 表示没有开启事务。因为这种方式压根不会执行:conn.setAutoCommit(false);
      • 在JDBC事务种,没有执行conn.setAutoCommit(false);那么autoCommit就是true
      • 如果autoCommit是true,就表示没有开启事务。只要执行任意一条DML语句就提交一次

    MANAGED事务管理器:

    • mybatis不再负责事务的管理了。事务管理交给其他容器来负责。例如:spring—— 我不管事务了,你来负责

    • 对于我们当前的单纯的只有mybatis的情况下,如果配置为:MANAGED
      那么事务这块是没人管的。没有人管理事务表示事务压根没有开启

    public class MyBatisIntroductionTest {
        public static void main(String[] args) throws IOException {
            //1.获取SqlSessionFactoryBuilder对象
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    
            //2.获取SqlSessionFactory对象,通过传入输入流的文件路径在工厂builder.build方法来进行创建
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");//填写mybatis-config.xml文件的路径
            //Resources.getResourceAsStream默认就是从类的根路径下开始查找资源
    
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);//一般情况下都是一个数据库对应一个SqlsessionFactory对象
    
    
            //3.获取SqlSession对象,通过工厂的openSession方法进行获取
    //        SqlSession sqlSession = sqlSessionFactory.openSession(); //如果使用的事务管理器是JDBC的话,底层实际上会执行: conn.setAutoCommit(false);
            //这种方式实际上是不建议的,因为么一开启事务
            SqlSession sqlSession = sqlSessionFactory.openSession(true);
    
            //4.执行SQL语句
            int count = sqlSession.insert("car");//放入设置的mapper文件里sql语句的id
            //返回值是影响数控表当中的记录条数
    
            System.out.println("插入了几条记录:" + count);
    
            //manager时
            //5.然后手动提交,因为SqlSession不支持自动提交
    //        sqlSession.commit(); 如果使用的事务管理器是JDBC的话,底层实际上还是会执行conn.commit();
    
            //6.关闭资源,(只关闭是不会提交的)
            sqlSession.close();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    JDBC的事务:

    • 如果没有在JDBC代码种执行:conn.setAutoCommit(false);的话,默认的autoCommimt是true

    完整的mybatis程序展示:

    package com.powernode.mybatis.test;
    
    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 java.io.IOException;
    
    public class MyBatisCompleteTestjava {
        //完整的写法
        public static void main(String[] args) {
            SqlSession sqlSession =null;
            try {
                SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
                SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
                //开启会(底层会开启事务)
                sqlSession = sqlSessionFactory.openSession();
                //执行SQL语句,处理相关业务
                int count = sqlSession.insert("car");
    
                //执行到这里,没有发生任何异常,提交事务,终止事务
                sqlSession.commit();
            } catch (IOException e) {
                //最好回滚事务
                if(sqlSession != null){
                    sqlSession.rollback();
                }
                e.printStackTrace();
            } finally {
                //关闭会话(释放资源)
                if(sqlSession != null){
                    sqlSession.close();
                }
            }
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    2.4 开发中的junit

    • JUnit是专门做单元测试的组件。
      • 在实际开发中,单元测试一般是由我们Java程序员来完成的。
      • 我们要对我们自己写的每一个业务方法负责任,要保证每个业务方法在进行测试的时候都能通过。
      • 测试的过程中涉及到两个概念:
        • 期望值
        • 实际值
      • 期望值和实际值相同表示测试通过,期望值和实际值不同则单元测试执行时会报错。
    • 这里引入JUnit是为了代替main方法。

    使用JUnit步骤:

    • 第一步:引入依赖
        
    <dependency>
        <groupId>junitgroupId>
        <artifactId>junitartifactId>
        <version>4.13.2version>
        <scope>testscope>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 第二步:编写单元测试类【测试用例】,测试用例中每一个测试方法上使用你要测试的类名+Test注解进行标注。
      • 测试用例的名字以及每个测试方法的定义都是有规范的:
      • 测试用例的名字:XxxTest
      • 测试方法声明格式:public void test业务方法名(){}
      • @Test注解非常重要,被这个注解标注的方法就是一个单元测试方法
    // 测试用例
    public class CarMapperTest{
        
        // 测试方法
        @Test
        public void testInsert(){
       		//单元测试中有两个重要的概念:
    		//一个是:实际值(被测试的业务方法的真正执行结果)
    		//一个是:期望值(执行了这个业务方法之后,你期望的执行结果是多少)
    
        }
        
        @Test
        public void testUpdate(){}
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 第三步:可以在类上执行,也可以在方法上执行
      • 在类上执行时,该类中所有的测试方法都会执行。
      • 在方法上执行时,只执行当前的测试方法。

    案例:

    import com.powernode.junit.service.MathService;
    import org.junit.Assert;
    import org.junit.Test;
    
    public class MathServiceTest {
        @Test
        public void testSum(){
            //单元测试中有两个重要的概念:
            //一个是:实际值(被测试的业务方法的真正执行结果)
            //一个是:期望值(执行了这个业务方法之后,你期望的执行结果是多少)
            MathService mathService = new MathService();
            //获取实际值
            int actual = mathService.sum(1, 2);
            //期望值
            int expected = 3;
    
            //加个断言进行测试
            Assert.assertEquals(expected,actual);
        }
    
        @Test
        public void testSub(){
            MathService mathService = new MathService();
            int actual = mathService.sub(10, 5);
    
            int expected = 5;
    
            Assert.assertEquals(expected,actual);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    在这里插入图片描述

    2.5 Mybatis 集成日志框架logback

    关于mybatis集成日志组件,让我们调试起来更加方便

    • mybatis常见的集成的日志组件有哪些呢

      • SLF4J(沙拉风):沙拉风是一个日志标准,其中有一个框架叫做logback,它实现了沙拉风规范
      • LOG4J
      • STDOUT_LOGGING…
    • 其中STDOUT_LOGGING是标准日志,mybatis已经实现了这种标准日志。mybatis框架本身已经实现了这种标准只要开启即可。

    怎么开启呢?

    mybatis-config.xml文件中使用settings标签进行配置开启。
    例如:

    • 这个标签在编写的时候需要注意,它应该出现在environments标签之前。注意顺序。当然,不需要记忆这个顺序。因为又dtd文件进行约束,只要参考dta约束即可
    • 这种实现也是可以的,可以看到一些信息,比如:连接对象什么时候创建,什么时候关闭,sql语句是怎样的
      在这里插入图片描述
      但是没有详细的日期,线程名字等。如果你想使用更加丰富的配置,可以集成第三方的log组件

    标准日志也可以用,但是配置不够灵活,可以集成其他的日志组件,例如:log4j,logback等。

    logback是目前日志框架中性能较好的,较流行的,所以我们选它。logback日志框架实现了slf4j标准

    引入logback的步骤:

    • 第一步:映入logback的依赖
    <dependency>
      <groupId>ch.qos.logbackgroupId>
      <artifactId>logback-classicartifactId>
      <version>1.2.11version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 第二步:引入logback所必须的xml配置文件(文件名叫做logback.xml或logback-test.xml,放到类路径当中)
      • 这个配置文件的名字必须叫做:logback.xml或者logback-test.xml,不能是其他的名字
      • 这个配置文件必须放到类的根路径下。不能是其他位置
      • 主要配置日志输出相关的级别以及日志具体的格式
    
    
    <configuration debug="false">
        
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
            encoder>
        appender>
        
        <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                
                <FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.logFileNamePattern>
                
                <MaxHistory>30MaxHistory>
            rollingPolicy>
            <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
            encoder>
            
            <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
                <MaxFileSize>100MBMaxFileSize>
            triggeringPolicy>
        appender>
    
        
        <logger name="com.apache.ibatis" level="TRACE"/>
        <logger name="java.sql.Connection" level="DEBUG"/>
        <logger name="java.sql.Statement" level="DEBUG"/>
        <logger name="java.sql.PreparedStatement" level="DEBUG"/>
    
        
        <root level="DEBUG">
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="FILE"/>
        root>
    
    configuration>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    开启的日志:
    在这里插入图片描述

    2.6 Mybatis工具类的编写

    创建utils包:
    在这里插入图片描述

    package com.powernode.mybatis.utils;
    
    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 java.io.IOException;
    
    //mybatis工具类
    public class SqlSessionUtil {
        //工具类的构造方法一般都是私有化的
        //工具类中的所有方法都是静态的,直接采用类名即可调用。不需要new对象
        // 为了防止new对象,构造方法私有化
        private SqlSessionUtil(){}
    
    
        private static SqlSessionFactory sqlSessionFactory;
        //类加载时执行
        //SqlSessionUtil工具类在进行第一次加载的时候,
        static {
            try {
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    //    public static SqlSession openSession() throws IOException {
    //        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    //        //SqlSessionFactory对象:一个SqlSessionFactory对于一个environment,一个environment通常是一个数据库环境
    //        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
    //        SqlSession sqlSession = sqlSessionFactory.openSession();
    //        return sqlSession;
    //    }
        public static SqlSession openSession(){
            return sqlSessionFactory.openSession();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    测试:

        @Test
        public void testInsertCarByUtil(){
            SqlSession sqlSession = SqlSessionUtil.openSession();
            int count = sqlSession.insert("car");
            System.out.println(count);
            sqlSession.commit();
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    三 小黑子教你MyBatis如何完成CRUD(增删改查)

    什么是CRUD?

    • C:create 增
    • R:retrieve 查(检索)
    • U:update 改
    • D:delete 删

    准备工作

    • 创建module(Maven的普通Java模块):mybatis-002-crud
    • pom.xml
      • 打包方式jar
      • 依赖:
        • mybatis依赖
        • mysql驱动依赖
        • junit依赖
        • logback依赖
      • mybatis-config.xml放在类的根路径下
      • CarMapper.xml放在类的根路径下
      • logback.xml放在类的根路径下
      • 提供com.powernode.mybatis.utils.SqlSessionUtil工具类
      • 创建测试用例:com.powernode.mybatis.CarMapperTest

    3.1 mybatis完成insert使用Map集合传参

    使用MAP集合传参
    分析以下SQL映射文件中SQL语句存在的问题

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <mapper namespace="car">
        <insert id="insertCar">
            insert into t_car(car_num,brand,guide_price,produce_time,car_type) values('103', '奔驰E300L', 50.3, '2022-01-01', '燃油车')
        insert>
    mapper>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这样写存在的问题是:

    • SQL语句中的值不应该是写死到配置文件里,值应该是用户提供的,这样子写在实际开发中不存在。
    • 一定是要前端的form表单提交过来数据,然后将值传递给sql语句

    之前的JDBC代码是这样写的:

    // JDBC中采用 ? 作为占位符。那么MyBatis中会使用什么作为占位符呢?
    String sql = "insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(?,?,?,?,?)";
    // ......
    // 给 ? 传值。那么MyBatis中应该怎么传值呢?
    //例如:
    ps.setString(1,"103");
    ps.setString(2,"奔驰E300L");
    ps.setDouble(3,50.3);
    ps.setString(4,"2022-01-01");
    ps.setString(5,"燃油车");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在MyBatis中可以这样做:

    • 在Java程序中,将数据放到Map集合中
    • 在sql语句中使用 #{map集合的key} 来完成传值,#{ } 等同于JDBC中的 ?#{}就是占位符

    范例:
    CarMapper.xml:

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="car">
        
        <insert id="insertCar">
            insert into t_car
                (id,car_num,brand,guide_price,produce_time,car_type)
            values
                (null,#{k1},#{k2},#{k3},#{k4},#{k5})#放入map集合的key
        insert>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    测试代码:

    package com.powernode.mybatis.test;
    
    import com.powernode.mybatis.utils.SqlSessionUtil;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.HashMap;
    
    public class CarMapperTest {
        @Test
        public void testInsertCar(){
            SqlSession sqlSession = SqlSessionUtil.openSession();
    
            //假装前端传过来数据了
            //这个对象我们先使用Map集合进行数据的封装
            HashMap<String, Object> map = new HashMap<>();
            map.put("k1","1111");
            map.put("k2","byd");
            map.put("k3",10.0);
            map.put("k4","2020-11-11");
            map.put("k5","电车");
    
    
            //执行sql语句
            //insert方法的参数
            //第一个参数:sqlid,从CarMapper.xml文件中复制
            //第二个参数:封装数据对象
            int count = sqlSession.insert("insertCar", map);
            System.out.println(count);
    
            sqlSession.commit();
            sqlSession.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    在这里插入图片描述
    在这里插入图片描述
    所以java程序中使用Map可以给sql语句的占位符传值:

            HashMap<String, Object> map = new HashMap<>();
            map.put("k1","1111");
            map.put("k2","byd");
            map.put("k3",10.0);
            map.put("k4","2020-11-11");
            map.put("k5","电车");
    
            insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,#{k1},#{k2},#{k3},#{k4},#{k5})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    注意:#{这里写什么?写map集合的key,如果key不存在,获取的是null}
    因此,一般map集合的key起名的时候要见名知意

    如下:

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="car">
        
        <insert id="insertCar">
            insert into t_car
                (id,car_num,brand,guide_price,produce_time,car_type)
            values
                (null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})#放入map集合的key
        insert>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    package com.powernode.mybatis.test;
    
    import com.powernode.mybatis.utils.SqlSessionUtil;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.HashMap;
    
    public class CarMapperTest {
        @Test
        public void testInsertCar(){
            SqlSession sqlSession = SqlSessionUtil.openSession();
    
            //假装前端传过来数据了
            //这个对象我们先使用Map集合进行数据的封装
            HashMap<String, Object> map = new HashMap<>();
            map.put("carNum","1111");
            map.put("brand","byd");
            map.put("guidePrice",10.0);
            map.put("produceTime","2020-11-11");
            map.put("carType","电车");
    
    
            //执行sql语句
            //insert方法的参数
            //第一个参数:sqlid,从CarMapper.xml文件中复制
            //第二个参数:封装数据对象
            int count = sqlSession.insert("insertCar", map);
            System.out.println(count);
    
            sqlSession.commit();
            sqlSession.close();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    3.1.1 使用POJO集合传参

    java程序中使用POJO类给SQL语句的占位符传值

    • 第一步:定义一个pojo类Car,提供相关属性。
      在这里插入图片描述
    package com.powernode.mybatis.pojo;
    
    //封装汽车相关信息的pojo类,普遍的java类
    public class Car {
        // 数据库表当中的字段应该和pojo类的属性一一对应
        //建议使用包装类Long,这样可以防止null的问题
        private Long id;
        private String carNum;
        private String brand;
        private Double guidePrice;
        private String produceTime;
        private String carType;
    
    
        @Override
        public String toString() {
            return "Car{" +
                    "id=" + id +
                    ", carNum='" + carNum + '\'' +
                    ", brand='" + brand + '\'' +
                    ", guidePrice=" + guidePrice +
                    ", produceTime='" + produceTime + '\'' +
                    ", carType='" + carType + '\'' +
                    '}';
        }
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getCarNum() {
            return carNum;
        }
    
        public void setCarNum(String carNum) {
            this.carNum = carNum;
        }
    
        public String getBrand() {
            return brand;
        }
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
    
        public Double getGuidePrice() {
            return guidePrice;
        }
    
        public void setGuidePrice(Double guidePrice) {
            this.guidePrice = guidePrice;
        }
    
        public String getProduceTime() {
            return produceTime;
        }
    
        public void setProduceTime(String produceTime) {
            this.produceTime = produceTime;
        }
    
        public String getCarType() {
            return carType;
        }
    
        public void setCarType(String carType) {
            this.carType = carType;
        }
    
        public Car(Long id, String carNum, String brand, Double guidePrice, String produceTime, String carType) {
            this.id = id;
            this.carNum = carNum;
            this.brand = brand;
            this.guidePrice = guidePrice;
            this.produceTime = produceTime;
            this.carType = carType;
        }
    
        public Car(){
    
        }
    
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 第二步:Java程序
      @Test
        public void testInsertCarByPOJO(){
            SqlSession sqlSession = SqlSessionUtil.openSession();
            //封装数据
    
           Car car = new Car(null,"3333","bydnmd",30.0,"2020-11-11","新能源");
    
            int count = sqlSession.insert("insertCar", car);//第一个放入的是CarMapper.xm里面的sqlid
            System.out.println(count);
            sqlSession.commit();
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 第三步:SQL语句,#{ } 里写的是POJO的属性名
    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="car">
        
        <insert id="insertCar">
                insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
                values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
        insert>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述
    在这里插入图片描述

    经过测试得出结论:
    在这里插入图片描述
    严格意义上来说:如果使用POJO对象传递值的话,#{}这个大括号中到底写什么?

    • 写的是get方法名去掉get,然后将剩下的单词首字母小写,然后放进去
      例如:getUsername() --> #{username}

    • 如果采用map集合传参,#{} 里写的是map集合的key,如果key不存在不会报错,数据库表中会插入NULL

    • 如果采用POJO传参,#{} 里写的是get方法的方法名去掉get之后将剩下的单词首字母变小写(例如:getAge对应的是#{age},getUserName对应的是#{userName},如果这样的get方法不存在会报错。

    注意:其实传参数的时候有一个属性parameterType,这个属性用来指定传参的数据类型,不过这个属性是可以省略的

    3.2 mybatis完成delete删除操作

    需求:根据id删除数据

    注意:当占位符只有一个的时候,${} 里面的内容可以随便写。

    • SQL语句写:
      注意:如果占位符只有一个,那么#{}的大括号里可以随意。但是最好见名知意思
    
        <delete id="deleteById">
            delete from t_car where id = #{SuiBianXie}
        delete>
    
    • 1
    • 2
    • 3
    • 4
    • Java程序
    @Test
        public void testDeleteById(){
            SqlSession sqlSession = SqlSessionUtil.openSession();
            int count = sqlSession.delete("deleteById", 5);
            System.out.println(count);
            sqlSession.commit();
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    3.3 mybatis完成update更新操作

    需求:根据id修改某条记录

    在这里插入图片描述

    • sql语句如下:
    <update id="updateById">
            update t_car set
                             car_num = #{carNum},
                             brand = #{brand},
                             guide_price = #{guidePrice},
                             produce_time = #{produceTime},
                             car_type = #{carType}
            where id = #{id}
    
        update>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 测试代码:
      @Test
        public void testUpdateById(){
            SqlSession sqlSession = SqlSessionUtil.openSession();
    
            //4L表示的是Long类型表示id:4 Long类型
            Car car = new Car(4L,"9999","magua",30.3,"1999-11-10","旧能源");
            int count = sqlSession.update("updateById", car);
            System.out.println(count);
            sqlSession.commit();
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述
    在这里插入图片描述

    当然,如果使用map传数据也是可以的

    3.4 mybatis完成select查询一个的操作

    select语句和其它语句不同的是:查询会有一个结果集对象:ResultSet。

    需求:查询id为1的Car信息

    • SQL语句如下:
        <select id="selectById">
            select * from t_car where id = #{id}
        select>
    
    • 1
    • 2
    • 3
    • 测试:
      在JDBC中叫做ReusltSet,接下来是mybatis应该从ResultSet中取出数据,封装java对象
    @Test
        public void testSelectById(){
            SqlSession sqlSession = SqlSessionUtil.openSession();
    
            //执行sql语句
            Object car = sqlSession.selectOne("selectById", 1);
            System.out.println(car);
            sqlSession.commit();
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    紧接着就报错了:
    表示:已运行查询,但未找到映射语句" "的结果映射。很有可能既没有指定结果类型也没有指定结果映射
    在这里插入图片描述

    • 运行后之前的异常不再出现了,这说明添加了resultType属性之后,解决了之前的异常,可以看出resultType是不能省略的:
    • 需要特别注意的是:select标签中resultType属性,这个属性用来告诉mybatis,查询结果集封装成说明类型的java对象。你需要告诉mybatis。reultType通常写的是:全限定类名
      在这里插入图片描述
        <select id="selectById" resultType="com.powernode.mybatis.pojo.Car">
            select * from t_car where id = #{id}
        select>
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    通过观察发现:只有id和brand是一致的,其他字段名和属性名对应不上,这是不是导致null的原因呢?

    • carNum以及其他的这几个属性没有赋上值的原因是:
      • 在这里插入图片描述
      • car_num、guide_price、produce_time、car_type这是查询结果的列名。
        这些列名和Car类中的属性名对不上。
      • car类的属性名:
        carNum、guidePrice、produceTime、carType

    那么这个问题该怎么解决?
    我们尝试在sql语句中使用as关键字来给查询结果列名起别名试试:

        <select id="selectById" resultType="com.powernode.mybatis.pojo.Car">
    
            select
                    id,car_num as carNum,brand,guide_price as guidePrice,
                   produce_time as procedureTime,
                   car_type as carType
            from t_car
            where id = #{id}
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    通过测试得知,如果当查询结果的字段名和java类的属性名对应不上的话,可以采用as关键字起别名,当然还有其它解决方案,我们后面再看。

    3.4.1 完成select查询所有

    需求:查询所有的Car信息

    • sql语句
     <select id="selectAll" resultType="com.powernode.mybatis.pojo.Car">
            select
                id,car_num as carNum,brand,guide_price as guidePrice,
                produce_time as procedureTime,
                car_type as carType
            from t_car
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 测试:
    @Test
        public void testSelectAll(){
            SqlSession sqlSession = SqlSessionUtil.openSession();
    
            List<Object> cars = sqlSession.selectList("selectAll");
            cars.forEach(car -> System.out.println(car));
    
            sqlSession.commit();
            sqlSession.close();
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述
    在这里插入图片描述

    注意:resultType还是指定要封装的结果集的类型。不是指定List类型,是指定List集合中元素的类型。selectList方法: mybatis通过这个方法就可以得知你需要一个List集合。它会自动给你返回一个List集合

    3.5 SQLMapper映射文件中namespace的作用

    在SQL Mapper配置文件中标签的namespace属性可以翻译为命名空间,这个命名空间主要是为了防止sqlId冲突的。

    • 创建UserMapper.xml文件,代码如下:
    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="aaaaaaaaaaaaaaa">
    
        <select id="selectAll" resultType="com.powernode.mybatis.pojo.Car">
            select
                id,car_num as carNum,brand,guide_price as guidePrice,
                produce_time as procedureTime,
                car_type as carType
            from t_car
        select>
    
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    不难看出,CarMapper.xml和UserMapper.xml文件中都有 id=“selectAll”
    将UserMapper.xml配置到mybatis-config.xml文件中

    • 测试
    @Test
    public void testNamespace(){
        // 获取SqlSession对象
        SqlSession sqlSession = SqlSessionUtil.openSession();
        // 执行SQL语句
        List<Object> cars = sqlSession.selectList("selectCarAll");
        // 输出结果
        cars.forEach(car -> System.out.println(car));
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    报错:
    在这里插入图片描述

    【翻译】selectCarAll在Mapped Statements集合中不明确(请尝试使用包含名称空间的全名,或重命名其中一个条目)
    【大致意思是】selectCarAll重名了,你要么在selectCarAll前添加一个名称空间,要有你改个其它名字。

    • 代码修改:
     @Test
        public void testNameSpace(){
            SqlSession sqlSession = SqlSessionUtil.openSession();
            //List cars = sqlSession.selectList("selectAll");
            //正确完整的写法:namespace.id
            List<Object> cars = sqlSession.selectList("aaaaaaaaaaaaaaa.selectAll");
            cars.forEach(car-> System.out.println(car));
            sqlSession.commit();
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    极简c++(7)类的继承
    第一章《嵌入式系统原理与实践》--沈建华 王慈 清华大学出版社 课后部分习题个人答案
    redis启动和简单使用
    【WCN685X】WCN6856 5G吞吐量测试只有25Mbps问题原因分析及解决方案
    VMWARE安装Ubuntu24.04桌面版的问题
    GpsModule 350+ 常用GPS坐标地图
    CompTIA美国计算机协会的热门认证一览
    【AutoAugment】《AutoAugment:Learning Augmentation Policies from Data》
    vue组件库发布到npm
    [ros2实操]1-ros2的安装(ubuntu1804)与运行
  • 原文地址:https://blog.csdn.net/VanWot/article/details/132479754