image.png

1、什么是Mybatis?

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


1.1 官方中文文档

https://mybatis.org/mybatis-3/zh/index.html

1.2 Mybatis特点

  • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
  • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
  • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库的orm字段关系映射
  • 提供对象关系映射标签,支持对象关系组建维护
  • 提供xml标签,支持编写动态sql。

2、Mybatis 使用

  • 由于mybatis是对数据库操作所以要使用maven导入MySQL
  • 使用mybatis需要导入mybatis
  • 单元测试引入
  • maven 网址:maven:https://mvnrepository.com/

    2.1 配置

  1. <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
  2. <dependency>
  3. <groupId>mysql</groupId>
  4. <artifactId>mysql-connector-java</artifactId>
  5. <version>8.0.16</version>
  6. </dependency>
  1. <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
  2. <dependency>
  3. <groupId>org.mybatis</groupId>
  4. <artifactId>mybatis</artifactId>
  5. <version>3.4.6</version>
  6. </dependency>
  1. <!-- https://mvnrepository.com/artifact/junit/junit -->
  2. <dependency>
  3. <groupId>junit</groupId>
  4. <artifactId>junit</artifactId>
  5. <version>4.12</version>
  6. <scope>test</scope>
  7. </dependency>

2.2 工具类

  • 每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。
  • SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。
  • SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。

从 XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件进行配置。 但也可以使用任意的输入流(InputStream)实例,比如用文件路径字符串或 file:// URL 构造的输入流。MyBatis 包含一个名叫 Resources 的工具类,它包含一些实用方法,使得从类路径或其它位置加载资源文件更加容易。

  1. String resource = "org/mybatis/example/mybatis-config.xml";
  2. InputStream inputStream = Resources.getResourceAsStream(resource);
  3. SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  • 以上方法可以为我们获得一个SqlSessionFactory , SqlSessionFactory可以为我们提供一个SqlSession, SqlSession就可以对数据库进行操作, 所以再项目前我们都要一个工具类来为我们产生SqlSession

    1. private static SqlSessionFactory sqlSessionFactory = null;
    2. static {
    3. try {
    4. String resource = "mybatis-config.xml";
    5. //工具类需要核心配置文件, 用里面的driver url username password来执行数据库操作
    6. InputStream inputStream = Resources.getResourceAsStream(resource);
    7. sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    8. }catch(Exception e){
    9. e.printStackTrace();
    10. }
    11. }
    12. public static SqlSession getSqlSession(){
    13. return sqlSessionFactory.openSession();
    14. }

2.3 从XML中构建SqlSessionFactory

  • 2.2 我们通过SqlSessionFactory 获得了SqlSession 但是SqlSessionFactory 是怎么得到的呢?
  • 观察2.2代码发现有一个String resource, resource字面理解资源的意思,这里的资源就是我们需要构建的SqlSessionFactory
  • 官方文档给出了SqlSessionFactory的XML构造方法如下:

    1. <?xml version="1.0" encoding="UTF-8" ?>
    2. <!DOCTYPE configuration
    3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
    5. <configuration>
    6. <environments default="development">
    7. <environment id="development">
    8. <transactionManager type="JDBC"/>
    9. <dataSource type="POOLED">
    10. <property name="driver" value="${driver}"/>
    11. <property name="url" value="${url}"/>
    12. <property name="username" value="${username}"/>
    13. <property name="password" value="${password}"/>
    14. </dataSource>
    15. </environment>
    16. </environments>
    17. <mappers>
    18. <mapper resource="org/mybatis/example/BlogMapper.xml"/>
    19. </mappers>
    20. </configuration>

    xml构造说明:

  • dirver: 就是JDBC驱动:com.mysql.cj.jdbc.Driver

  • url : 通过JDBC访问数据库

jdbc:mysql://localhost:3306/test?userSSL=true&useUnicode=true&characterEncoding=UTF- 8&serverTimezone=UTC

  • name : 数据库登录用户名
  • password : 登录密码

  • 特别注意下面的代码:

    1. <mappers>
    2. <mapper resource="org/mybatis/example/BlogMapper.xml"/>
    3. </mappers>

    这里表示注册mapper, 意思就是哪个地方需要访问数据库,写有映射数据库的语句的xml文档都要在核心配置文档也就是上面的文档中注册

2.4实体类

  • 实体类就是所需数据库里面的数据组成的类
  • 包含构造方法 get方法, toString方法 等
  • 实体类就是Myratis SqlSession 返回的数据类型

2.5定义接口

  • 接口里面包含了需要操作数据库的方法以及返回的数据结构
  • 这个接口不需要另外写方法来实现直接通过xml文件来实现,2.3里面的特别注意要注册的xml文件就是这个接口实现xml文件
  • 具体如下

    2.6接口实现

    1. <?xml version="1.0" encoding="UTF-8" ?>
    2. <!DOCTYPE mapper
    3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="org.mybatis.example.BlogMapper">
    6. <select id="selectBlog" resultType="Blog">
    7. select * from Blog where id = #{id}
    8. </select>
    9. </mapper>

    说明:

  • namespace 名称空间就是对应的所需要实现的接口的位置以及名字,为了避免出错通常使用全名称即具体位置

  • id : 所需要实现接口里面的方法 即 namespace对应接口里面的某一个方法 这里只需要填写方法名
  • resultType : 结果类型, 就是自己写的那个实体类类型, 这里需要填写实体类的具体包名加上类名
  • 中间的就是sql语句了
  • 特别注意:

    • 实体类里面的数据类型和 变量名必须和MySQL里面的字段名字一一对应

      2.7 单元测试

  • 为了保证代码的准确性, 需要进行单元测试

    3、根据2的例子

    3.1 准备一个数据库

    image.png

    3.2创建一个maven项目

    创建maven项目导入MySQL Myratis Junit

    1. <dependency>
    2. <groupId>mysql</groupId>
    3. <artifactId>mysql-connector-java</artifactId>
    4. <version>8.0.16</version>
    5. </dependency>
    6. <dependency>
    7. <groupId>org.mybatis</groupId>
    8. <artifactId>mybatis</artifactId>
    9. <version>3.4.6</version>
    10. </dependency>
    11. <dependency>
    12. <groupId>junit</groupId>
    13. <artifactId>junit</artifactId>
    14. <version>4.12</version>
    15. <scope>test</scope>
    16. </dependency>

    3.3创建工具类

    ```xml package com.qzw.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.InputStream;

public class MybatisUtils {

  1. private static SqlSessionFactory sqlSessionFactory = null;
  2. static {
  3. try {
  4. String resource = "mybatis-config.xml";
  5. //工具类需要核心配置文件, 用里面的driver url username password来执行数据库操作
  6. InputStream inputStream = Resources.getResourceAsStream(resource);
  7. sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  8. }catch(Exception e){
  9. e.printStackTrace();
  10. }
  11. }
  12. public static SqlSession getSqlSession(){
  13. return sqlSessionFactory.openSession();
  14. }

}

  1. <a name="Hh52F"></a>
  2. ## 3.4从xml中构建SqlSessionFactory
  3. ```xml
  4. <?xml version="1.0" encoding="UTF-8" ?>
  5. <!DOCTYPE configuration
  6. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  7. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  8. <configuration>
  9. <environments default="development">
  10. <environment id="development">
  11. <transactionManager type="JDBC"/>
  12. <dataSource type="POOLED">
  13. <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
  14. <property name="url" value="jdbc:mysql://localhost:3306/test?userSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC"/>
  15. <property name="username" value="root"/>
  16. <property name="password" value="Aa123456"/>
  17. </dataSource>
  18. </environment>
  19. </environments>
  20. <mappers>
  21. <mapper resource="com/qzw/dao/UserMapper.xml"/>
  22. </mappers>
  23. </configuration>

3.5实体类

  1. package com.qzw.pojo;
  2. public class User {
  3. private int Stuld;
  4. private String StuName;
  5. private String LoginPwd;
  6. public User() {
  7. }
  8. public User(int stuld, String stuName, String loginPwd) {
  9. Stuld = stuld;
  10. StuName = stuName;
  11. LoginPwd = loginPwd;
  12. }
  13. public int getStuld() {
  14. return Stuld;
  15. }
  16. public String getStuName() {
  17. return StuName;
  18. }
  19. public String getLoginPwd() {
  20. return LoginPwd;
  21. }
  22. public String toString(){
  23. return Stuld+StuName+LoginPwd;
  24. }
  25. }

3.6定义接口

  1. package com.qzw.dao;
  2. import com.qzw.pojo.User;
  3. import java.util.List;
  4. public interface UserDao {
  5. List<User> getUserList();
  6. }

3.7接口实现

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.qzw.dao.UserDao">
  6. <select id="getUserList" resultType="com.qzw.pojo.User">
  7. select Stuld, StuName, LoginPwd from students
  8. </select>
  9. </mapper>

3.8单元测试

  • 特别注意: 为了高效利用资源SqlSession打开了一定要关闭 ```xml package com.qzw.dao;

import com.qzw.pojo.User; import com.qzw.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test;

import java.util.List;

public class UserMapperTest { @Test public void selectUser(){ //先获取一个sqlsession SqlSession sqlSession = MybatisUtils.getSqlSession(); //执行getMapper 结果是实现的一个接口 UserDao userDao = sqlSession.getMapper(UserDao.class); //用执行实现接口类里面的方法 List list = userDao.getUserList();

  1. for(User u : list){
  2. System.out.println(u);
  3. }
  4. sqlSession.close();
  5. }

}

  1. <a name="5HkB0"></a>
  2. ## 3.9 目录
  3. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/365532/1605345982212-5e34085f-a267-4163-bfd7-4355b4c94ebc.png#align=left&display=inline&height=328&margin=%5Bobject%20Object%5D&name=image.png&originHeight=656&originWidth=282&size=25168&status=done&style=none&width=141)
  4. <a name="9HLTk"></a>
  5. # 4、关于接口实现xml的具体说明
  6. ```xml
  7. <?xml version="1.0" encoding="UTF-8" ?>
  8. <!DOCTYPE mapper
  9. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  10. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  11. <mapper namespace="org.mybatis.example.BlogMapper">
  12. <select id="selectBlog" resultType="Blog">
  13. select * from Blog where id = #{id}
  14. </select>
  15. </mapper>

4.1namespace

  • namespace 表示命名空间 就是指要实现的接口
  • namespace 要指向到具体的包

    4.2 select

    1. <select id="getUser" parameterType="int" resultType="com.qzw.pojo.User">
    2. select Stuld, StuName, LoginPwd from students where Stuld = #{id}
    3. </select>
  • d 对应的是接口里面的方法

  • parameterType 表示的参数类型
  • resultType 表示sql 查询返回值的类型
  • { } 就是我们使用的参数id

    4.3 update

    1. <update id="updateUser" parameterType="com.qzw.pojo.User">
    2. update students set StuName = #{StuName} where Stuld = #{Stuld} ;
    3. </update>
  • id 对应的是接口里面的方法

  • parameterType表示的是参数类型: 这里的参数就是接口方法里面的参数User,同样要指向到具体的包
  • { } 的作用就是User对象里面对应的属性 写出属性名字即可

    4.4 delete insert

  • id parameterType 跟上面两个意义一样

  • 没有返回值类型 返回的是一个int 类型表示的是查询的结果数量

5、关于单元测试的说明

  1. @Test
  2. public void tset2(){
  3. SqlSession sqlSession = MybatisUtils.getSqlSession();
  4. UserDao userDao = sqlSession.getMapper(UserDao.class);
  5. int num = userDao.updateUser(new User(4,"周瑜","123123"));
  6. sqlSession.commit(); //提交事务, 否则无法保存到数据库
  7. sqlSession.close();
  8. }

以这个更新数据为例

  • 第一步 用工具类产生一个SqlSession 对象

    1. SqlSession sqlSession = MybatisUtils.getSqlSession();
  • 第二部 利用SqlSession 对象实现定义的接口

    1. UserDao userDao = sqlSession.getMapper(UserDao.class);
  • 第三步 执行接口里面的方法

    1. int num = userDao.updateUser(new User(4,"周瑜","123123"));
  • 第四步 增删改一定要提交事务,否则数据库不会发生任何改变

    1. sqlSession.commit();
  • SQLSession 一旦打开一定要关闭

    1. sqlSession.close();

    6、parameterType参数传递的问题

    6.1 使用Map简化

  • 在一个数据库中有表过多表中字段过多,在增删改查的时候使用实体类需要构造很多属性这是可直接使用map

  • Map传参的时候只需传递Map的key就可以

如下:
image.png
在这张表里面我们查询的时候使用实体类需要构造11个字段, 但是有时候自需要用户名和密码两个字段,使用实体类就比较麻烦,所以使用Map来传递

接口方法如下

  1. //使用Map进行参数传递
  2. User getUser2(Map<String,Object> map);

xml

  1. <select id="getUser2" parameterType="Map" resultType="com.qzw.pojo.User">
  2. select Stuld, StuName, LoginPwd from students where Stuld = #{id} and StuName = #{name}
  3. </select>

测试

  1. public void test4(){
  2. SqlSession sqlSession = MybatisUtils.getSqlSession();
  3. UserDao userDao = sqlSession.getMapper(UserDao.class);
  4. Map<String, Object> map = new HashMap<String,Object>();
  5. map.put("id",1);
  6. map.put("name","张飞");
  7. User u = userDao.getUser2(map);
  8. System.out.println(u);
  9. sqlSession.close();
  10. }

6.2 防止sql注入

  • 模糊查询或则其他操作的时候避免使用拼接防止sql注入

    1. <select id="getUser2" parameterType="Map" resultType="com.qzw.pojo.User">
    2. select Stuld, StuName, LoginPwd from students where StuName like #{name}
    3. </select>
    1. public void test4(){
    2. SqlSession sqlSession = MybatisUtils.getSqlSession();
    3. UserDao userDao = sqlSession.getMapper(UserDao.class);
    4. Map<String, Object> map = new HashMap<String,Object>();
    5. map.put("name","%张%");
    6. User u = userDao.getUser2(map);
    7. System.out.println(u);
    8. sqlSession.close();
    9. }
  • 直接在Map里面写好通配符,避免使用拼接