Mybatis从入门到精通(全)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
日志服务 SLS,月写入数据量 50GB 1个月
简介: 目录前言1. mybatis了解前言项目框架中 mybatis用于数据访问层界面层:servlet–springmvc业务逻辑层:service类–spring数据访问层:dao类–mybatis三层的访问交互是依次进行 在深入访问数据库后依次退出而mybatis框架的好处对比mybatis与jdbc、hibernate的对比:jdbc:代码比较多,开发效率低,重复代码多,业务代码和数据库操作混杂一起。在代码块中对象要创建和销毁,查询的结果要封装list。hibernate:全自动m

前言

项目框架中 mybatis用于数据访问层
界面层:servlet--springmvc
业务逻辑层:service类--spring
数据访问层:dao类--mybatis
三层的访问交互是依次进行 在深入访问数据库后依次退出

==了解更多mybatis 可查看==
mybatis入门中文文档

该文章的学习主要通过视频进行总结汇总
2020最新MyBatis教程【IDEA版】-MyBatis从入门到精通

该文章的学习代码如下
mybatis从入门到精通的学习代码.rar

1. idea软件小技巧

  • ctrl+alt+shift+c 复制全限定名称 相当于copy reference
  • ctrl+shift+o 相当于reimport
  • 创建类文件 =包名.类名 会自动生成包与类
  • 无法创建xml文件,可以直接创建普通文件,名字后缀加xml
  • 代码变红色,引入class包名,alt+enter

2. mybatis优势

==而mybatis框架的好处对比==

mybatis与jdbc、hibernate的对比:

jdbc:代码比较多,开发效率低,重复代码多,业务代码和数据库操作混杂一起。在代码块中对象要创建和销毁,查询的结果要封装list。
hibernate:全自动
mybatis:提供访问数据库基本功能,半自动,sql与java编码分离,轻量级的框架

回顾jdbc的代码可看我之前的文章
jdbc从入门到精通(全)
学完之后,发现jdbc的代码

  • 业务代码和数据库的操作混在一起
  • 重复的代码比较多

为此减轻使用 JDBC 的复杂性,不用编写重复的创建 Connetion , Statement ; 不用编写关闭资源代码。直接使用 java 对象,表示结果数据。让开发者专注 SQL 的处理。 其他分心的工作由 MyBatis 代劳

mybatis两大功能:

  • sql mapper:sql映射,可以把数据库表中的一行数据,映射为一个java对象,操作此对象即操作此数据
  • dao类:数据访问,进行数据增删改查

写sql即可,不必关心Connection,Statement,ResultSet的创建,销毁,sql的执行

  • MyBatis 是一个优秀的基于 java 的持久层框架,内部封装了 jdbc,开发者只需要关注 sql 语句本身,而不需要处理加载驱动、创建连接、创建statement、关闭连接,资源等繁杂的过程。
  • MyBatis 通过 xml 或注解两种方式将要执行的各种 sql 语句配置起来,并通过 java 对象和 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。

3. mybatis入门项目

3.1 项目具体步骤

这个具体步骤比较重要
可以边建立项目的时候边想代码是如何调用

  • 新建数据表
  • maven配置以及在pom.xml中加入mybatis坐标和mysql驱动依赖 还有xml的生成配置(因为类路径下不会自动生成)
  • 创建类,保存表中的数据
  • 创建dao接口,定义操作数据库方法接口方法。
  • 创建mapper文件,即在同一目录下定义sql映射文件,写sql文件和接口方法对应的sql语句
  • 创建mybatis主配置文件(提供数据库连接信息和xml中sql的映射信息(指定mapper文件的位置),也就是类路径的具体位置。
  • 创建mybatis类(SqlSession对象),来访问数据库sql

3.2 创建数据表

将java与数据库连接
涉及数据库可看我上一篇文章
数据库中增删改常用语法语句(全)
数据库查询常用语句语法

CREATE TABLE `student` (
 `id` int(11) NOT NULL ,
 `name` varchar(255) DEFAULT NULL,
 `email` varchar(255) DEFAULT NULL,
 `age` int(11) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3.3 创建maven项目

项目启用maven,具体配置可查看我上一篇文章
Maven详细配置(全)
在这里插入图片描述
在这里插入图片描述
项目启动成功后截图 出现build success
在这里插入图片描述

3.4 pom.xml配置文件

  • 坐标、mybatis依赖和mysql驱动
  • 扫描的xml插件、编译器版本和单元测试
<!--坐标 -->
  <groupId>org.example</groupId>
  <artifactId>mybatis</artifactId>
  <version>1.0-SNAPSHOT</version>


  <!--配置该有的编译器版本,此版本为1.8 -->
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <!--单元测试 -->
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>


    <!--mybatis依赖 -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.1</version>
    </dependency>

    <!--mysql驱动 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.9</version>
    </dependency>
  </dependencies>

还要添加一个xml的配置文件
因为java默认文件路径识别不到xml的后缀
之后再target下才会生成

 <!--扫描xml插件 -->
<build>
    <resources>
      <resource>
        <directory>src/main/java</directory><!--所在的目录-->
        <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>
  </build>

配置好之后ctrl+shift+o更新配置或者是右键在maven中 reimport

3.5 数据类、接口类和映射文件

创建一个数据类,包含数据的定义,设值以及获取等

//推荐和表名一样。容易记忆
public class Student {
    //定义属性, 目前要求是属性名和列名一样。
    private Integer id;
    private String name;
    private String email;
    private Integer age;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                '}';
    }
}

创建另一个包,包含接口类和配置文件
创建一个包含所有数据的列表,每个数据就是一个对象
用该方法来调用数据

//查询student表的所有的数据
    public List<Student> selectStudents();

而这个数据要用在该类中同一目录之中,同一包之下的xml文件

==mybatis会执行这些sql文件,具体格式代码说明:==

1.dtd为约束文件,限制和检查出现的标签是否符合mybatis定义的规则
2.mapper为根标签,namespace为命名空间,可以自定义的字符串,最好用dao接口全限定名称
3.使用特定标签表示数据库特定操作
~select查询,update更新,insert插入,delete删除
~3.1 内部名称为 id是sql的唯一标识,mybatis会通过id值执行sql语句,可以任意定值,但最好用接口中方法的名称调用
~3.2 resultType为结果类型,执行sql后得到resultSet,并且遍历它所得到java对象类型。==类比jdbc的创建数据集==即执行的sql数据得到的结果,最后一一赋给java对象获取,最好用全限定名称,也就是实体类的全限定名称

总结:

  • dao接口全限定名称用在mapper的根标签
  • id为方法名
  • resultType为返回的实体类对象全限定名称

==namespace为接口名,id为方法名,resultType为定义的类名==
==后面定义的测试类中 执行数据库语句的字符串即为接口名.方法名==

<?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.bjpowernode.dao.StudentDao">
    <!--
       select:表示查询操作。
       id: 你要执行的sql语法的唯一标识, mybatis会使用这个id的值来找到要执行的sql语句
           可以自定义,但是要求你使用接口中的方法名称。

       resultType:表示结果类型的, 是sql语句执行后得到ResultSet,遍历这个ResultSet得到java对象的类型。
          值写的类型的全限定名称
    -->
    <select id="selectStudents" resultType="com.bjpowernode.domain.Student" >
        select id,name,email,age from student order by id
    </select>
</mapper>

==总之id用列表定义的方法名,namespace和resultType用全限定名称路径名==

3.6 mybatis主配置文件

这个主配置文件和jdbc文件中的这个代码功能一致
在这里插入图片描述

新建一个resources目录并且设置改目录为resources root
在这里插入图片描述
在该目录下新建一个mybatis.xml的配置文件

  • dtd约束文件名称
  • configuration根标签
  • environments 环境配置为连接数据库的信息,default需要与environment某个id值一样,表示需要使用哪个数据库信息
  • environment 数据库配置信息,id唯一值 表示环境名称
  • transactionManager为mybatis的事务类型
  • dataSource表示数据源,连接数据库

主要看代码中的注释也可以

==数据库连接信息==

<environments default="mydev">
        <!-- environment : 一个数据库信息的配置, 环境
             id:一个唯一值,自定义,表示环境的名称。
        -->
        <environment id="mydev">
            <!--
               transactionManager :mybatis的事务类型
                   type: JDBC(表示使用jdbc中的Connection对象的commit,rollback做事务处理)
            -->
            <transactionManager type="JDBC"/>
            <!--
               dataSource:表示数据源,连接数据库的
                  type:表示数据源的类型, POOLED表示使用连接池
            -->
            <dataSource type="POOLED">
                <!--
                   driver, user, username, password 是固定的,不能自定义。
                -->
                <!--数据库的驱动类名-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!--连接数据库的url字符串-->
                <property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
                <!--访问数据库的用户名-->
                <property name="username" value="root"/>
                <!--密码-->
                <property name="password" value="123456"/>
            </dataSource>
        </environment>

==sql映射mapper位置==
一个mapper标签指定一个文件位置,可以用多个mapper标签指定
==这个文件位置间隔需要用 /==
点击maven的compile编译即可

上面的pom.xml配置了识别xml配置文件
会在target/clasess(类路径)下生成
具体调用的映射文件的位置(通过target/clasess(类路径))要通过mapper进行映射

<!-- sql mapper(sql映射文件)的位置-->
    <mappers>
        <!--一个mapper标签指定一个文件的位置。
           从类路径开始的路径信息。  target/clasess(类路径)
        -->
        <mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
        <!--<mapper resource="com/bjpowernode/dao/SchoolDao.xml" />-->
    </mappers>

==做项目整合的时候只需要修改
数据库的连接信息以及sql映射位置即可
其他都雷同,只需修改此处两个位置==

3.7 测试文件

在生成的/target/class下有xml配置文件路径
(class文件中必须要有主配置文件)

  • 用sql的SqlSessionFactory对象调用读取的主配置文件
  • 以此来打开session文件,赋值给SqlSessionFactoryBuilder对象
  • 通过sql文件映射的执行语句输出结果

具体怎么识别是哪个xml配置文件
主要通过xml配置文件中的namespace的命名空间
com.bjpowernode.dao.StudentDao(为全限定名称名)+selectStudents(方法名)
最后为com.bjpowernode.dao.StudentDao.selectStudents

public static void main(String[] args) throws IOException {
        //访问mybatis读取student数据
        //1.定义mybatis主配置文件的名称, 从类路径的根开始(target/clasess)
        String config="mybatis.xml";
        //2.读取这个config表示的文件
        InputStream in = Resources.getResourceAsStream(config);
        //3.创建了SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder  = new SqlSessionFactoryBuilder();
        //4.创建SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(in);
        //5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //6.【重要】指定要执行的sql语句的标识。  sql映射文件中的namespace + "." + 标签的id值
        //String sqlId = "com.bjpowernode.dao.StudentDao" + "." + "selectStudents";
        //namespace.id值为sqlId的执行语句
     
        String sqlId = "com.bjpowernode.dao.StudentDao.selectStudents";
        //7. 重要】执行sql语句,通过sqlId找到语句
        List<Student> studentList = sqlSession.selectList(sqlId);
        //8.输出结果
        //studentList.forEach( stu -> System.out.println(stu));
        for(Student stu : studentList){
            System.out.println("查询的学生="+stu);
        }
        //9.关闭SqlSession对象
        sqlSession.close();

    }

运行的即种解决方法:

  • maven插件的 clean->compile
  • 窗口中build的rebuild project
  • 窗口中file的Invalidate Caches
  • 手工拷贝复制target不存在的文件

在编译过程中如果出现以下问题
可查看我之前的文章

  1. 出现Could not find resource mybatis.xml的解决方法
  2. 出现target\surefire-reports for the individual test results的解决方法

编译成功之后的数据展示台如下
在这里插入图片描述
配合数据库表可一一验证
在这里插入图片描述

3.8 dubug代码

  • ==定义一个配置文件之后直接获取配置文件==

在这里插入图片描述

进入到直接获取配置文件的源码,直接获取
在这里插入图片描述
return返回另一个代码函数
在这里插入图片描述
在调用另外一个函数,也就是类加载器
在这里插入图片描述
一直遍历判断直到他是为止
在这里插入图片描述

  • ==用sql的SqlSessionFactory对象调用读取的主配置文件==

在这里插入图片描述
具体源码内部如下
在这里插入图片描述
在这里插入图片描述

  • ==以此来打开session文件,赋值给SqlSessionFactoryBuilder对象==

在这里插入图片描述

3.9 配置文件模板

1.映射文件模板

<?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="接口包名全名称">
    <select id=" 方法名" resultType="含数据的类名全名称">
       
    </select>

</mapper>

2.主配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <!--settings:控制mybatis全局行为-->
    <settings>
        <!--设置mybatis输出日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <environments default="mydev">
        <environment id="mydev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">   <!--数据库连接池-->
                <!--数据库的驱动类名-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!--连接数据库的url字符串-->
                <property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
                <!--访问数据库的用户名-->
                <property name="username" value="root"/>
                <!--密码-->
                <property name="password" value="123456"/>
            </dataSource>
        </environment>

    </environments>

    <!-- sql mapper(sql映射文件)的位置-->
    <mappers>
        <mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
        <!--<mapper resource="com/bjpowernode/dao/SchoolDao.xml" />-->
    </mappers>
</configuration>

idea具体设置位置:
在这里插入图片描述

3.10 功能添加-插入元素

基于以上项目进行整改
添加额外的插入数据库元素的功能
数据库的增删改查,原本有查询功能,现在额外补充一个插入元素功能

1.接口类中补充插入元素的方法
插入的元素为类对象,返回结果为数据行数,即int类型

//插入方法
    //参数: student ,表示要插入到数据库的数据
    //返回值: int , 表示执行insert操作后的 影响数据库的行数
    public int insertStudent(Student student);

2.与接口类中同一目录下的sql映射文件xml中 添加一个插入元素
id最好用插入方法类
插入的具体格式是 #{ },没有返回的实体类类型,所以不用resultType这个属性

<!--插入操作-->
    <insert id="insertStudent">
        insert into student values(#{id},#{name},#{email},#{age})
    </insert>

以上两个文件的具体位置如下
在这里插入图片描述

3.测试类中额外几个函数

//6.【重要】指定要执行的sql语句的标识。  sql映射文件中的namespace + "." + 标签的id值
        String sqlId = "com.bjpowernode.dao.StudentDao.insertStudent";
        //7. 重要】执行sql语句,通过sqlId找到语句
        Student student  = new Student();
        student.setId(1006);
        student.setName("关羽");
        student.setEmail("guanyu@163.com");
        student.setAge(20);
        int nums = sqlSession.insert(sqlId,student);

        //mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务
        //sqlSession.commit();

添加代码主要通过sqlSession这个类中的函数
这个函数源码是
在这里插入图片描述
==第一个为sql语句,第二个为对象参数==

完整代码如下:

public class TestMyBatis {
    //测试方法,测试功能
    @Test
    public void testInsert() throws IOException {

        //访问mybatis读取student数据
        //1.定义mybatis主配置文件的名称, 从类路径的根开始(target/clasess)
        String config="mybatis.xml";
        //2.读取这个config表示的文件
        InputStream in = Resources.getResourceAsStream(config);
        //3.创建了SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder  = new SqlSessionFactoryBuilder();
        //4.创建SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(in);
        //5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //SqlSession sqlSession = factory.openSession(true);
        //6.【重要】指定要执行的sql语句的标识。  sql映射文件中的namespace + "." + 标签的id值
        String sqlId = "com.bjpowernode.dao.StudentDao.insertStudent";
        //7. 重要】执行sql语句,通过sqlId找到语句
        Student student  = new Student();
        student.setId(1006);
        student.setName("关羽");
        student.setEmail("guanyu@163.com");
        student.setAge(20);
      
        int nums = sqlSession.insert(sqlId,student);

        //mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务
        sqlSession.commit();

        //8.输出结果
        System.out.println("执行insert的结果="+nums);

        //9.关闭SqlSession对象
        sqlSession.close();
    }
}

编译完成之后,需要提交事务才可看到新增加的数据,mybatis默认是没有提交事务

即在insert ,update ,delete后要手工提交事务

//mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务
        sqlSession.commit();

insert ,update ,delete这些数据在编译器的输出平台中看不到
需要添加一个日志才可看到
具体日志的配置在下面

具体显示结果如下(添加了日志)

在这里插入图片描述
查看其数据库的结果如下
在这里插入图片描述
具体可看我这篇文章
添加数据到数据库中显示乱码的解决方法

3.11 日志提交

需要在mybatis.xml主配置文件中添加一个日志
才会在编译器看到修改数据库的结果

<!--settings:控制mybatis全局行为-->
    <settings>
        <!--设置mybatis输出日志-->
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>

4. 改进步骤

4.1 常用类介绍

介绍如何改进的时候
先介绍下常用类的代码逻辑

//访问mybatis读取student数据
//1.定义mybatis主配置文件的名称, 从类路径的根开始(target/clasess)
String config="mybatis.xml";
//2.读取这个config表示的文件
InputStream in = Resources.getResourceAsStream(config);
//3.创建了SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder  = new SqlSessionFactoryBuilder();
//4.创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
//5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
//SqlSession sqlSession = factory.openSession();
SqlSession sqlSession = factory.openSession(true);
//6.【重要】指定要执行的sql语句的标识。  sql映射文件中的namespace + "." + 标签的id值
String sqlId = "com.bjpowernode.dao.StudentDao.insertStudent";
//7. 重要】执行sql语句,通过sqlId找到语句
Student student  = new Student();
student.setId(1006);
student.setName("关羽");
student.setEmail("guanyu@163.com");
student.setAge(20);
int nums = sqlSession.insert(sqlId,student);

//mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务
sqlSession.commit();

//8.输出结果
System.out.println("执行insert的结果="+nums);

//9.关闭SqlSession对象
sqlSession.close();

主要是介绍上面这些方法中的具体步骤以及使用过程

  • 1. Resources:读取主配置文件,是mybatis的一个类
  InputStream in = Resources.getResourceAsStream("mybatis.xml");
  • 2. SqlSessionFactoryBuilder : 创建SqlSessionFactory对象

主要的过程是先创建自我的实体类对象,之后通过自我实体类对象创建一个SqlSessionFactory对象

SqlSessionFactoryBuilder builder  = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);

总体来说就是

SqlSessionFactory  factory = new SqlSessionFactoryBuilder().build(in);
  • 3.SqlSessionFactory :接口类,整个项目有一个此对象即可

获取SqlSession对象,SqlSession sqlSession = factory.openSession();
openSession() :无参数, 非自动提交事务SqlSession
openSession(true) : 自动提交事务的SqlSession
openSession(false) 非自动提交事务的SqlSession

即在接口类这样定义即可

//5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession = factory.openSession(true);

==上下两条语句对等==

//5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession = factory.openSession();
//mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务
sqlSession.commit();

//或者直接写
SqlSession sqlSession = factory.openSession(true);
  • ==4.SqlSession接口 :定义了操作数据的方法==

有selectOne() ,selectList() ,insert(),update(), delete(), commit(), rollback()等
SqlSession对象不是线程安全的,即执行sql语句之前,使用openSession()获取SqlSession对象。执行结束后关闭SqlSession.close(),这样才是安全的

SqlSession的实现类是DefaultSqlSession,都重写了这些方法,主要是多态的一个使用方法

4.2 封装工具类

将常用类进行封装
大部分都是一样的

public class MyBatisUtils {

    private  static  SqlSessionFactory factory = null;
    static {
        String config="mybatis.xml"; // 需要和你的项目中的文件名一样
        try {
            InputStream in = Resources.getResourceAsStream(config);
            //创建SqlSessionFactory对象,使用SqlSessionFactoryBuild
            factory = new SqlSessionFactoryBuilder().build(in);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    //获取SqlSession的方法
    public static SqlSession getSqlSession() {
        SqlSession sqlSession  = null;
        if( factory != null){
            sqlSession = factory.openSession();// 非自动提交事务
        }
        return sqlSession;
    }
}

在测试类的完整代码如下:

public class MyApp2 {

    public static void main(String[] args) throws IOException {

        //获取SqlSession对象,从SqlSessionFactory中获取SqlSession
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        //【重要】指定要执行的sql语句的标识。  sql映射文件中的namespace + "." + 标签的id值
        String sqlId = "com.bjpowernode.dao.StudentDao.selectStudents";
        //【重要】执行sql语句,通过sqlId找到语句
        List<Student> studentList = sqlSession.selectList(sqlId);
        //输出结果
        studentList.forEach( stu -> System.out.println(stu));
        //关闭SqlSession对象
        sqlSession.close();

    }

}

4.3 传统dao类改进

本身
在这里插入图片描述
StudentDao类很少用到,主要还是用到了sqlsession的方法,StudentDao类主要是做一个指引的指示

为了封装更好的使用重写这个类的方法

主要区别在于改写接口类的方法,以便在测试类中直接定义,和传统写法保持一致,定义的接口和测试类分隔开

获取数据库,执行sql语句,在测试类进行书写

public class StudentDaoImpl implements StudentDao {
    @Override
    public List<Student> selectStudents() {
        //获取SqlSession对象
        //通过封装类进行执行
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        //主要是这个sql语句
        String sqlId="com.bjpowernode.dao.StudentDao.selectStudents";
        //执行sql语句, 使用SqlSession类的方法
        List<Student> students  = sqlSession.selectList(sqlId);
        //关闭
        sqlSession.close();
        return students;
    }
    @Override
    public int insertStudent(Student student) {
        //获取SqlSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        String sqlId="com.bjpowernode.dao.StudentDao.insertStudent";
        //执行sql语句, 使用SqlSession类的方法
        int nums = sqlSession.insert(sqlId,student);
        //提交事务
        sqlSession.commit();
        //关闭
        sqlSession.close();
        return nums;
    }
}

测试类的定义
通过调用执行类
在调用执行类的方法

public class TestMyBatis {

    @Test
    public void testSelectStudents(){
        //com.bjpowernode.dao.StudentDao
        StudentDao dao  = new StudentDaoImpl();
        List<Student> studentList  = dao.selectStudents();
        for(Student stu:studentList){
            System.out.println(stu);
        }
    }

    @Test
    public void testInsertStudent(){
        StudentDao dao  = new StudentDaoImpl();
        Student student = new Student();
        student.setId(1005);
        student.setName("盾山");
        student.setEmail("dunshan@qq.com");
        int nums = dao.insertStudent(student);
        System.out.println("添加对象的数量:"+nums);
    }

}

==通过以上改写接口类和测试类的代码中,可以看到很多冗余一样的代码,只不过几处不一样而已,其实还可以继续封装==

5. 动态代理

关于这部分知识涉及到了jdk的动态代理
可看我之前的文章进行了解
jdk动态代理(AOP)从入门到精通(全)

xml文件定义如下
在这里插入图片描述
通过调用执行类来执行xml下的sql文件(也就是映射对象)

  • StudentDao dao = new StudentDaoImpl();这个语句调用dao对象,类型是StudentDao,全限定名称是:com.bjpowernode.dao.StudentDao,全限定名称 和 namespace 是一样的。
  • List<Student> studentList = dao.selectStudents(); 通过dao中方法的返回值也可以确定MyBatis要调用的SqlSession的方法,也就是查看xml配置文件中的定义

如果返回值是List ,调用的是SqlSession.selectList()方法
如果返回值 int ,或是非List的,看mapper文件中的标签是<insert>,<update> 就会调用SqlSession的insert, update等方法

==以此引出动态代理的结构,节省代码量,也就是测试类可以不用这么冗余,也不用定义实现类==

  • mybatis根据 dao的方法调用,获取执行sql语句的信息
  • mybatis根据dao接口,创建dao接口的实现类, 并创建该类的对象,完成SqlSession调用方法, 访问数据库

具体如何创建如何执行

==使用mybatis的动态代理机制, 使用SqlSession.getMapper(dao接口),getMapper能获取dao接口对于的实现类对象==
mybatis内部通过接口名和方法名映射到对应xml文件中的sql语句执行

将其上面的测试类和实现类合并变成一个
直接调用封装类
具体如下

SqlSession sqlSession = MyBatisUtils.getSqlSession();
//通过动态代理得到其类的对象
StudentDao dao  =  sqlSession.getMapper(StudentDao.class);

//com.sun.proxy.$Proxy2 : jdk的动态代理
System.out.println("dao="+dao.getClass().getName());
//调用dao的方法, 执行数据库的操作
List<Student> students = dao.selectStudents();
for(Student stu: students){
    System.out.println("学生="+stu);
}

以及添加的测试代码如下

@Test
public void testInsertStudent(){
    SqlSession sqlSession  = MyBatisUtils.getSqlSession();
    StudentDao dao  =  sqlSession.getMapper(StudentDao.class);

    Student student = new Student();
    student.setId(1007);
    student.setName("李飞");
    student.setEmail("dunshan@qq.com");
    student.setAge(28);
    int nums = dao.insertStudent(student);
    sqlSession.commit();
    System.out.println("添加对象的数量:"+nums);
}

5.1 参数剖析

==parameterType==
此处也是重点讲解一个参数该如何使用

  • 接口中方法参数的类型, 类型的完全限定名或别名
    例如:parameterType="java.lang.Integer"

            parameterType="int"
  • parameterType不是强制的,mybatis通过反射机制能够发现接口参数的数类型,可以没有,一般不写

主要写在dao.xml的配置文件下

<select id="selectStudentById" parameterType="java.lang.Integer" resultType="com.bjpowernode.domain.Student">
        select id,name, email,age from student where id=${id}
</select>

或者是

<select id="selectStudentById" parameterType="int" resultType="com.bjpowernode.domain.Student">
        select id,name, email,age from student where id=${id}
</select>

5.2 深入理解参数

5.2.1 单参数

主要写在dao.xml的配置文件下

<select id="selectStudentById" resultType="com.bjpowernode.domain.Student">
        select id,name, email,age from student where id=${id}
</select>

具体接口类的定义如下

public Student selectStudentById(Integer id)

使用#{}之后, mybatis执行sql是使用的jdbc中的PreparedStatement对象
由mybatis执行下面的代码:

  1. mybatis创建Connection , PreparedStatement对象
String sql="select id,name, email,age from student where id=?";
PreparedStatement pst = conn.preparedStatement(sql);
pst.setInt(1,1001);
  1. 执行sql封装为resultType="com.bjpowernode.domain.Student"这个对象
ResultSet rs = ps.executeQuery();
Student student = null;
while(rs.next()){
//从数据库取表的一行数据, 存到一个java对象属性中
student = new Student();
student.setId(rs.getInt("id));
student.setName(rs.getString("name"));
student.setEmail(rs.getString("email"));
student.setAge(rs.getInt("age"));
}

return student;  //给了dao方法调用的返回值

5.2.2 多参数

==@Param==
多个参数: 命名参数,在形参定义的前面加入 @Param("自定义参数名称")

xml文件的定义

<!--多个参数,使用@Param命名-->
<select id="selectMultiParam" resultType="com.bjpowernode.domain.Student">
     select id,name, email,age from student where name=#{myname} or age=#{myage}
</select>

dao类接口的定义

List<Student> selectMultiParam(@Param("myname") String name,
                               @Param("myage") Integer age);

具体测试类的书写如下

@Test
public void testSelectMultiParam(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    List<Student> students = dao.selectMultiParam("李四",20);

    for(Student stu: students){
        System.out.println("学生="+stu);
    }
    sqlSession.close();
}

==使用对象==
使用java对象作为接口中方法的参数

List<Student> selectMultiStudent(Student student);

使用java对象的属性值,作为参数实际值

使用对象语法: #{属性名,javaType=类型名称,jdbcType=数据类型} 很少用。

  • javaType:指java中的属性数据类型。
  • jdbcType:在数据库中的数据类型。

例如: #{paramName,javaType=java.lang.String,jdbcType=VARCHAR}

我们使用的简化方式: #{属性名} ,javaType, jdbcType的值mybatis反射能获取。不用提供

很少使用


<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
          select id,name, email,age from student where
           name=#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
           or age=#{paramAge,javaType=java.lang.Integer,jdbcType=INTEGER}
</select>

一般这样使用

<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
      select id,name, email,age from student where
       name=#{paramName}   or age=#{paramAge}
</select>

测试类的代码

@Test
public void testSelectMultiStudent(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    Student student  = new Student();
    student.setName("张三");
    student.setAge(28);

    List<Student> students = dao.selectMultiStudent(student);

    for(Student stu: students){
        System.out.println("学生="+stu);
    }
    sqlSession.close();
}

==按照位置==
不推荐,不是很灵活

  • mybatis.3.4之前,使用 #{0} ,#{1}
  • mybatis。3.4之后 ,使用 #{arg0} ,#{arg1}
List<Student> selectMultiPosition( String name,Integer age);

xml文件的定义

<select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">
      select id,name, email,age from student where
      name = #{arg0} or age=#{arg1}
</select>

直接在测试类的时候一一对应进行输入

@Test
public void testSelectMultiPosition(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);



    List<Student> students = dao.selectMultiPosition("李四",20);

    for(Student stu: students){
        System.out.println("学生="+stu);
    }
    sqlSession.close();
}

==多个参数,使用Map存放多个值==
不推荐,不是很灵活

List<Student> selectMultiByMap(Map<String,Object> map);

xml文件的配置

<select id="selectMultiByMap" resultType="com.bjpowernode.domain.Student">
      select id,name, email,age from student where
      name = #{myname} or age=#{age1}
</select>

通过放置一个key值进行一一相应

@Test
public void testSelectMultiByMap(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    Map<String,Object> data = new HashMap<>();
    data.put("myname","张三");
    data.put("age1",28);

    List<Student> students = dao.selectMultiByMap(data);

    for(Student stu: students){
        System.out.println("学生="+stu);
    }
    sqlSession.close();
}

5.2.3 占位符

关于占位符的知识点,可看我之前的文章补充
jdbc之问号占位符的详细分析

对比一下两个占位符#$

  • # 的占位符
 select id,name, email,age from student where id = #{id}

最后的结果是 select id,name, email,age from student where id =?

  • $ 的占位符
 select id,name, email,age from student where id = ${id}

最后的结果是 select id,name, email,age from student where id =1001

  1. $这个占位符使用的是字符串的拼接
    使用的是statement对象执行sql,效率比PreparedStatement要低

    1. $可以替换表名或者列名,如果确定数据安全可以使用这个

具体两者的区别

  1. # 使用?占位符,使用的是PreparedStatement执行sql,效率高,避免了sql注入,更加安全
  2. $ 不使用?占位符,使用字符串连接,statement对象执行sql,效率低。有sql注入风险,安全性低。可以替换表名或者列名

==所谓的替换列名是这个意思==

List<Student> selectUse$Order(@Param("colName") String colName);

xml文件定义如下

<select id="selectUse$Order" resultType="com.bjpowernode.domain.Student">
     select * from student order by ${colName}
</select>

测试代码如下

@Test
public void testSelectUse$Order(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    List<Student> students = dao.selectUse$Order("age");

    for(Student stu: students){
        System.out.println("学生="+stu);
    }
    sqlSession.close();
}

==所谓的数据安全与否==
因为是字符串的拼接
所以如果语句结构是这样dao.selectUse$("'李四';select * from user");
引入字符串'',内容是sql语句,可以实现sql注入修改后台数据,造成数据不安全

5.2.4 总结

回顾一下之前的知识点
大致如下

动态代理:mybatis创建dao接口的实现类,在实现类中调用sqlsession方法执行sql语句
getmapper创建对象的时候本身就是一个jdk动态代理方式
com.sun.proxy.$Proxy2 : jdk的动态代理
在这里插入图片描述
在这里插入图片描述
之后获取到sqlsession的执行方法,获取其sql语句结构

使用动态代理的方式:

  • 获取sqlsession对象
  • 使用getmapper方法获取接口对象
  • 调用接口方法,执行mapper文件的sql语句

通过debug 剖析其源码
部分截图如下
具体getmapper

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

在这里插入图片描述

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

5.3 封装mybatis输出结果

5.3.1 resultType

mybatis执行了sql语句,得到java对象
具体执行的思路是
mybatis执行sql语句, 然后mybatis调用类的无参数构造方法,创建对象
mybatis把ResultSet指定列值付给同名的属性

<select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">
     select id,name, email,age from student
</select>

在对等的jdbc时
分别通过setId进行配对

ResultSet rs = executeQuery(" select id,name, email,age from student" )
while(rs.next()){
    Student  student = new Student();
    student.setId(rs.getInt("id"));
    student.setName(rs.getString("name"))
}

在这里插入图片描述

  • 简单类型
<!--sql执行后返回一行一列-->
<!--<select id="countStudent" resultType="int">-->
<select id="countStudent" resultType="java.lang.Integer">
    select count(*) from student
</select>
  • 对象类型
List<Student> selectMultiParam(@Param("myname") String name,
                                   @Param("myage") Integer age);
<!--多个参数,使用@Param命名-->
<select id="selectMultiParam" resultType="com.bjpowernode.domain.Student">
     select id,name, email,age from student where name=#{myname} or age=#{myage}
</select>
  • map类型

==只能最多返回一行记录。多余一行是错误==

//定义方法返回Map
    Map<Object,Object> selectMapById(Integer id);
<!--返回Map
    1)列名是map的key, 列值是map的value
    2)只能最多返回一行记录。多余一行是错误
-->
<select id="selectMapById" resultType="java.util.HashMap">
    select id,name,email from student where id=#{stuid}
</select>

具体测试文件如下

//返回Map
@Test
public void testSelecMap(){

    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao  =  sqlSession.getMapper(StudentDao.class);

    Map<Object,Object> map = dao.selectMapById(1001);
    System.out.println("map=="+map);
}

5.3.2 别名

再mybatis.xml配置文件中定义别名的配置
之后就可以直接使用自已定义的实体类的全限定名称的别名

第一种方式(可读性很差,很少使用)

可以指定一个类型一个自定义别名

  • type:自定义类型的全限定名称
  • alias:别名
<typeAliases>

    <typeAlias type="com.bjpowernode.domain.Student" alias="stu" />
    <typeAlias type="com.bjpowernode.vo.ViewStudent" alias="vstu" />
</typeAliases>

第二种方式(很少使用,会出错)

  • <package> name是包名, 这个包中的所有类,类名就是别名(类名不区分大小写)
<!--定义别名-->
<typeAliases>
  
    <package name="com.bjpowernode.domain"/>
    <package name="com.bjpowernode.vo"/>
</typeAliases>

最后的类名就是别名

最后一种别名的格式很少使用
因为如果在同一个文件中定义有两个同名类,会不知道引用哪个

5.3.3 resultMap

可以定义多行数据
使用resultMap定义映射关系

List<Student> selectAllStudents();

xml文件的定义
将其property=column 这样赋值

<!--定义resultMap
    id:自定义名称,表示你定义的这个resultMap
    type:java类型的全限定名称
-->
<resultMap id="studentMap" type="com.bjpowernode.domain.Student">
    <!--列名和java属性的关系-->
    <!--注解列,使用id标签
        column :列名
        property:java类型的属性名
    -->
    <id column="id" property="id" />
    <!--非主键列,使用result-->
    <result column="name" property="name" />
    <result column="email" property="email" />
    <result column="age" property="age" />

</resultMap>
<select id="selectAllStudents" resultMap="studentMap">
    select id,name, email , age from student
</select>

具体测试类的定义如下

@Test
public void testSelectAllStudents(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    List<Student> students = dao.selectAllStudents();

    for(Student stu: students){
        System.out.println("学生="+stu);
    }
    sqlSession.close();
}

==property 要与实体类的定义一样
而column 要与select 的定义一样==

第二种方式是

使用resultType的属性,之后再定义的时候通过
数据库名 id查询 映射到实体类中的的结果 进行辨别

或者直接在数据库中修改别名,和实体类一致就可以使用

<!--列名和属性名不一样:第二种方式
   resultType的默认原则是 同名的列值赋值给同名的属性, 使用列别名(java对象的属性名)
-->
<select id="selectDiffColProperty" resultType="com.bjpowernode.domain.MyStudent">
    select id as stuid ,name as stuname, email as stuemail , age stuage from student
</select>

5.4 模糊like

==第一种模糊查询, 在java代码指定 like的内容==

List<Student> selectLikeOne(String name);
<!--第一种 like , java代码指定 like的内容-->
<select id="selectLikeOne" resultType="com.bjpowernode.domain.Student">
    select id,name,email,age from student where name like #{name}
</select>

测试类的代码如下

@Test
public void testSelectLikeOne(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    //准备好like的内容
    String name = "%李%";
    List<Student> students = dao.selectLikeOne(name);

    for(Student stu: students){
        System.out.println("#######学生="+stu);
    }
    sqlSession.close();
}

==name就是李值, 在mapper中拼接 like "%" 李 "%" ==

List<Student> selectLikeTwo(String name);

这种方式 "%" #{name} "%"中间一定要带空格

<!--第二种方式:在mapper文件中拼接 like的内容-->
<select id="selectLikeTwo" resultType="com.bjpowernode.domain.Student">
    select id,name,email,age from student where name  like "%" #{name} "%"
</select>

测试类的代码如下

@Test
public void testSelectLikeTwo(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    //准备好like的内容
    String name = "张";
    List<Student> students = dao.selectLikeTwo(name);

    for(Student stu: students){
        System.out.println("*******学生="+stu);
    }
    sqlSession.close();
}

6. 动态sql

6.1 if结构

<if>是判断条件的,
   语法<if test="判断java对象的属性值">
            部分sql语句
        </if>

<if:test="使用参数java对象的属性值作为判断条件,语法 属性=XXX值">

//动态sql ,使用java对象作为参数
List<Student> selectStudentIf(Student student);
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
    select id,name, age, email from student
    where 
    <if test="name !=null and name !='' ">
       name = #{name}
    </if>
    <if test="age > 0">
        or age > #{age}
    </if>
</select>

测试代码如下

@Test
public void testSelectStudentIf(){

    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao  =  sqlSession.getMapper(StudentDao.class);

    Student student  = new Student();
    student.setName("李四");
    student.setAge(20);
    List<Student> students = dao.selectStudentIf(student);
    for(Student stu:students){
        System.out.println("if==="+stu);
    }

但是这种写法有缺陷
如果第一个if不满足了,第二个if 前面会带一个or结构 变成where or 就不对了
为了避免这种规则
可以这样书写xml文件

在前面的条件加上恒等式或者本身属性就会成立的条件

where 1=1
<if test="name !=null and name !='' ">
and name = #{name}

6.2 where结构

当多个if有一个成立的, <where>会自动增加一个where关键字,并去掉 if中多余的 and ,or等

//where使用
List<Student> selectStudentWhere(Student student);
where: <where> <if> <if>...</where>
<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
    select id,name, age, email from student
    <where>
        <if test="name !=null and name !='' ">
            name = #{name}
        </if>
        <if test="age > 0">
            or age > #{age}
        </if>
    </where>
</select>

也就是当其中一个if条件成立的时候 就会有where,如果都没成立,就没有where
成立的时候还会去掉前面的多余的 or 或者and

6.3 foreach结构

==添加常用的类型结构==

  • collection:表示接口中的方法参数的类型, 如果是数组使用array , 如果是list集合使用list
  • item:自定义的,表示数组和集合成员的变量
  • open:循环开始是的字符
  • close:循环结束时的字符
  • separator:集合成员之间的分隔符
//foreach 用法 1
    List<Student> selectForeachOne(List<Integer> idlist);
<!--foreach使用1 , List<Integer>-->
<select id="selectForeachOne" resultType="com.bjpowernode.domain.Student">
    select * from student where id in
    <foreach collection="list" item="myid" open="(" close=")" separator=",">
              #{myid}
    </foreach>

</select>

具体拼接测试代码如下

  • 添加列表
  • 用builder来遍历添加列表的值

==重要代码的逻辑思路==

@Test
public void testfor(){
    List<Integer> list = new ArrayList<>();
    list.add(1001);
    list.add(1002);
    list.add(1003);

    //String sql="select * from student where id in (1001,1002,1003)";
    String sql="select * from student where id in";

    StringBuilder builder  = new StringBuilder("");
    int init=0;
    int len = list.size();

    //添加开始的 (
    builder.append("(");
    for(Integer i:list){
        builder.append(i).append(",");

    }
    builder.deleteCharAt(builder.length()-1);
    //循环结尾
    builder.append(")");
    sql = sql  + builder.toString();
    System.out.println("sql=="+sql);


}

这种思路在leetcode中的列表拼接很常用
在这里插入图片描述


添加对象为类型

//foreach 用法 2
List<Student> selectForeachTwo(List<Student> stulist);
<select id="selectForeachTwo" resultType="com.bjpowernode.domain.Student">
    select * from student where id in
    <foreach collection="list" item="stu" open="("  close=")" separator=",">
             #{stu.id}
    </foreach>

</select>

具体的测试代码如下

@Test
public void testSelectForTwo(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao  =  sqlSession.getMapper(StudentDao.class);

    List<Student> stuList  = new ArrayList<>();
    Student s1 = new Student();
    s1.setId(1002);
    s1.setName("lisi");
    stuList.add(s1);

    s1 = new Student();
    s1.setId(1005);;
    s1.setName("zs");
    stuList.add(s1);

    List<Student> students = dao.selectForeachTwo(stuList);
    for(Student stu:students){
        System.out.println("foreach--two ==="+stu);
    }
}

6.4 动态sql

1.先定义 <sql id="自定义名称唯一"> sql语句, 表名,字段等 </sql>
2.再使用, <include refid="id的值" />

<!--定义sql片段-->
<sql id="studentSql">
    select id,name, age, email from student
</sql>

之后在下边这样定义

<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
    <include refid="studentSql" />
    where id > 0
    <if test="name !=null and name !='' ">
       and name = #{name}
    </if>
    <if test="age > 0">
        or age > #{age}
    </if>
</select>

7. 配置文件

  • 定义别名
  • 数据源
  • mapper 文件

其中定义别名上面已经讲过了这里就回顾一下

<!--定义别名-->
<typeAliases>
    <!--
        第一种方式:
        可以指定一个类型一个自定义别名
        type:自定义类型的全限定名称
        alias:别名(短小,容易记忆的)
    -->
    <!--<typeAlias type="com.bjpowernode.domain.Student" alias="stu" />
    <typeAlias type="com.bjpowernode.vo.ViewStudent" alias="vstu" />-->

    <!--
      第二种方式
      <package> name是包名, 这个包中的所有类,类名就是别名(类名不区分大小写)
    -->
    <package name="com.bjpowernode.domain"/>
    <package name="com.bjpowernode.vo"/>
</typeAliases>

7.1 数据库配置

数据库的属性配置文件: 把数据库连接信息放到一个单独的文件中。 和mybatis主配置文件分开。
目的是便于修改,保存,处理多个数据库的信息。

在resources目录中定义一个属性配置文件, xxxx.properties ,例如 jdbc.properties
在属性配置文件中, 定义数据,格式是 key=value

key: 一般使用 . 做多级目录的。
例如 jdbc.mysql.driver , jdbc.driver, mydriver
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql//.....
jdbc.username=root
jdbc.password=123456

在mybatis的主配置文件,使用<property> 指定文件的位置
在需要使用值的地方, ${key}

jdbc的配置文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springdb
jdbc.user=root
jdbc.passwd=123456

xml文件配置

<!--指定properties文件的位置,从类路径根开始找文件-->
<properties resource="jdbc.properties" />

具体的下面的配置文件这么定义
在这里插入图片描述
具体链接数据库文件的注释如下

<environments default="mydev">
    <environment id="mydev">
        <!--
          transactionManager:mybatis提交事务,回顾事务的方式
             type: 事务的处理的类型
                 1)JDBC : 表示mybatis底层是调用JDBC中的Connection对象的,commit, rollback
                 2)MANAGED : 把mybatis的事务处理委托给其它的容器(一个服务器软件,一个框架(spring))
        -->
        <transactionManager type="JDBC"/>
        <!--
           dataSource:表示数据源,java体系中,规定实现了javax.sql.DataSource接口的都是数据源。
                      数据源表示Connection对象的。

           type:指定数据源的类型
              1)POOLED: 使用连接池, mybatis会创建PooledDataSource类
              2)UPOOLED: 不使用连接池, 在每次执行sql语句,先创建连接,执行sql,在关闭连接
                          mybatis会创建一个UnPooledDataSource,管理Connection对象的使用
              3)JNDI:java命名和目录服务(windows注册表)
        -->
        <dataSource type="POOLED">
            <!--数据库的驱动类名-->
            <property name="driver" value="${jdbc.driver}"/>
            <!--连接数据库的url字符串-->
            <property name="url" value="${jdbc.url}"/>
            <!--访问数据库的用户名-->
            <property name="username" value="${jdbc.user}"/>
            <!--密码-->
            <property name="password" value="${jdbc.passwd}"/>
        </dataSource>
    </environment>
</environments>

7.2 mapper位置

mapper(sql映射文件)的位置

  • 第一种方式:指定多个mapper文件
<!-- sql mapper(sql映射文件)的位置-->
<mappers>
    <mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
    <mapper resource="com/bjpowernode/dao/OrderDao.xml" />
</mappers>
  • 第二种方式: 使用包名

name: xml文件(mapper文件)所在的包名, 这个包中所有xml文件一次都能加载给mybatis使用package的要求:

  1. mapper文件名称需要和接口名称一样, 区分大小写的一样
  1. mapper文件和dao接口需要在同一目录
<!-- sql mapper(sql映射文件)的位置-->
<mappers>
    <package name="com.bjpowernode.dao"/>
   <!-- <package name="com.bjpowernode.dao2"/>
    <package name="com.bjpowernode.dao3"/>-->
</mappers>

8. PageHelper

分页的功能
添加依赖包

<!--PageHelper依赖-->
<dependency>
  <groupId>com.github.pagehelper</groupId>
  <artifactId>pagehelper</artifactId>
  <version>5.1.10</version>
</dependency>

在mybatis.xml下添加插件
这个插件的功能类似数据库关键字中的limit

<!--配置插件-->
<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor" />
</plugins>

通过一个方法测试使用

//使用PageHelper分页数据
List<Student> selectAll();
<!--查询所有-->
<select id="selectAll" resultType="com.bjpowernode.domain.Student">
    select * from student order by id
</select>

具体的测试代码如下

@Test
public void testSelectAllPageHelper(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao  =  sqlSession.getMapper(StudentDao.class);
    //加入PageHelper的方法,分页
    // pageNum: 第几页, 从1开始
    // pageSize: 一页中有多少行数据
    PageHelper.startPage(1,3);
    List<Student> students = dao.selectAll();
    for(Student stu:students){
        System.out.println("foreach--one ==="+stu);
    }
}
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
5月前
|
SQL Java 数据库连接
MyBatis 框架入门理论与实践
MyBatis 框架入门理论与实践
66 6
|
4月前
|
XML Java 数据库连接
MyBatis入门——MyBatis XML配置文件(3)
MyBatis入门——MyBatis XML配置文件(3)
56 6
|
4月前
|
Java 关系型数据库 数据库连接
MyBatis入门(1)
MyBatis入门(1)
60 2
|
5月前
|
Java 数据库连接 测试技术
MyBatis-Plus入门
MyBatis-Plus入门
|
2月前
|
SQL Java 数据库连接
Spring Boot联手MyBatis,打造开发利器:从入门到精通,实战教程带你飞越编程高峰!
【8月更文挑战第29天】Spring Boot与MyBatis分别是Java快速开发和持久层框架的优秀代表。本文通过整合Spring Boot与MyBatis,展示了如何在项目中添加相关依赖、配置数据源及MyBatis,并通过实战示例介绍了实体类、Mapper接口及Controller的创建过程。通过本文,你将学会如何利用这两款工具提高开发效率,实现数据的增删查改等复杂操作,为实际项目开发提供有力支持。
61 0
|
4月前
|
Java 关系型数据库 数据库连接
技术好文共享:第一讲mybatis入门知识
技术好文共享:第一讲mybatis入门知识
32 6
|
4月前
|
Java 关系型数据库 MySQL
Mybatis入门之在基于Springboot的框架下拿到MySQL中数据
Mybatis入门之在基于Springboot的框架下拿到MySQL中数据
39 4
|
4月前
|
Java 程序员
浅浅纪念花一个月完成Springboot+Mybatis+Springmvc+Vue2+elementUI的前后端交互入门项目
浅浅纪念花一个月完成Springboot+Mybatis+Springmvc+Vue2+elementUI的前后端交互入门项目
45 1
|
4月前
|
SQL Java 数据库连接
MyBatis入门——MyBatis的基础操作(2)
MyBatis入门——MyBatis的基础操作(2)
25 4
|
4月前
|
Java 数据库连接 数据库
Spring日志完结篇,MyBatis操作数据库(入门)
Spring日志完结篇,MyBatis操作数据库(入门)
下一篇
无影云桌面