Java Mybatis狂神说的详细笔记(完整版)
Mybatis官方文档:
Mybatis官方文档
官网文档: https://mybatis.org/mybatis-3/zh/getting-started.html
MyBatis
1、简介
1.1 什么是Mybatis

- MyBatis 是一款优秀的持久层框架;
- 它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
1.2 持久化
数据持久化
- 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
- 内存:断电即失
- 数据库(Jdbc),io文件持久化。
为什么要持久化?
有一些对象,不能让他丢掉
内存太贵
1.3 持久层
Dao层、Service层、Controller层
- 完成持久化工作的代码块
- 层界限十分明显
1.4 为什么需要MyBatis
-
帮助程序员将数据存入到数据库中
-
方便
-
传统的JDBC代码太复杂了,简化,框架,自动化
-
不用MyBatis也可以,技术没有高低之分
-
优点:
- 简单易学
- 灵活
- sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql
2、第一个Mybatis程序
思路:搭建环境 --> 导入MyBatis --> 编写代码 --> 测试
2.1 搭建环境
创建数据库
CREATE DATABASE `mybatis`; USE `mybatis`; CREATE TABLE `user`( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `name` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户名称', `pwd` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户密码', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; INSERT INTO `user`(`id`,`name`,`pwd`) VALUES (1,"狂神","123456"), (2,"通达","123456"), (3,"蓝凌","123456");
新建项目
1.创建一个普通的maven项目
2.删除src目录 (就可以把此工程当做父工程了,然后创建子工程)
3.导入maven依赖
mysql mysql-connector-java 8.0.12 org.mybatis mybatis 3.5.4 junit junit 4.12 test
4.创建一个Module
2.2 创建一个模块
- 编写mybatis的核心配置文件
<?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">default="development">
详解:<?xml version="1.0" encoding="UTF-8" ?>
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
此处设useSSL=false。
- 编写mybatis工具类
//SqlSessionFactory -->SqlSession public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory; static { try { //使用Mybaties第一步:获取sqlSessionFactory对象 String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (Exception e) { e.printStackTrace(); } } //既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。 // SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。 public static SqlSession getSqlSession(){ // SqlSession sqlSession = sqlSessionFactory.openSession(); // return sqlSession; return sqlSessionFactory.openSession(); } }
2.3 编写代码
- 实体类
//实体类 public class User { private int id; private String name; private String pwd; public User() { } public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } }
- Dao接口
public interface UserDao { ListgetUserList(); }
- 接口实现类由原来的UserDaoImpl转变成一个Mapper配置文件。
<?xml version="1.0" encoding="UTF-8" ?>
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
junit测试.
注意点:会报错
org.apache.ibatis.binding.BindingException: Type interface com.kuang.dao.UserDao is not known to the MapperRegistry.
MapperRegistry是什么?
核心配置文件中注册mappers
@Test public void test(){ //1.获取SqlSession对象 SqlSession sqlSession = MybatisUtils.getSqlSession(); //2.执行SQL // 方式一:getMapper UserDao userDao = sqlSession.getMapper(UserDao.class); ListuserList = userDao.getUserList(); for (User user : userList) { System.out.println(user); } //关闭sqlSession sqlSession.close(); }
mybatis-config.xml中
可能会遇到的问题:
- 配置文件没有注册
- 绑定接口错误
- 方法名不对
- 返回类型不对
- Maven导出资源问题
3、CURD
1. namespace
namespace中的包名要和Dao/Mapper接口的包名一致
<?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">
2. select
选择,查询语句;
id:就是对应的namespace中的方法名;
resultType : Sql语句执行的返回值;
parameterType : 参数类型;
1.编写接口:UserMapper.java
public interface UserMapper { //查询所有用户 public ListgetUserList(); //插入用户 public void addUser(User user); }
2.编写对应的mapper中的sql语句:UserMapper.xml
insert into user (id,name,password) values (#{id}, #{name}, #{password})
3.测试:UserMapperTest.java
@Test public void test2() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = new User(3,"黑子","666"); mapper.addUser(user); //增删改一定要提交事务 sqlSession.commit(); //关闭sqlSession sqlSession.close(); }
注意:增删改查一定要提交事务:
sqlSession.commit();
增删改查全部流程实现
3. Insert
4. update
5. Delete
UserMapper.java
//Dao以后等价mapper public interface UserMapper { //返回所有用户 ListgetUserList(); //根据Id查询用户,User为返回值用户 User getUserById(int id); //insert一个用户,参数是对象User int addUser(User user); //修改用户 int updateUser(User user); //删除一个用户 int deleteUser(int id); }
UserMapper.xml
<?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">
insert into mybatis.user(id,name,pwd) values(#{id},#{name},#{pwd});
update mybatis.user set name=#{name},pwd=#{pwd} where id =#{id};
delete from mybatis.user where id =#{id};
UserDaoTest.java
package com.tongda.dao; import com.tongda.pojo.User; import com.tongda.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.List; /** * @Author JunLong * @Date 2022/4/5 6:59 * @Version 1.0 */ /*注意点: org.apache.ibatis.binding.BindingException: Type interface com.kuang.dao.UserDao is not known to the MapperRegistry. MapperRegistry是什么? 核心配置文件中注册mappers */ public class UserDaoTest { @Test public void test(){ //第一步:获取SqlSession对象,工具类MybatisUtils中 SqlSession sqlSession = MybatisUtils.getSqlSession(); //执行Sql:方式一getMapper UserMapper mapper = sqlSession.getMapper(UserMapper.class); ListuserList = mapper.getUserList(); // 方法一: for (User user : userList) { System.out.println(user); } //不推荐:方法二 // List userList = sqlSession.selectList("com.tongda.UserDao.getUserList"); // for (Object user : userList) { // System.out.println(user); // // } //关闭sqlSession sqlSession.close(); } @Test public void getUserById(){ //第一步固定步骤写法 SqlSession sqlSession = MybatisUtils.getSqlSession(); //获得UserMapper接口 UserMapper mapper = sqlSession.getMapper(UserMapper.class); //getUserbyid(用户id号) User user1 = mapper.getUserById(1); User user2 = mapper.getUserById(2); User user3 = mapper.getUserById(2); System.out.println(user1); System.out.println(user2); System.out.println(user3); sqlSession.close(); } //增删改必须提交事务 @Test public void addUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); int res = mapper.addUser(new User(4, "哼哈", "123456")); if (res>0){ System.out.println("插入成功!"); } // 提交事务,增删改必须提交事务 sqlSession.commit(); //关闭 sqlSession.close();; } @Test public void updataUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); mapper.updateUser(new User(4,"呵呵","123123")); sqlSession.commit(); sqlSession.close(); } @Test public void deleteUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); mapper.deleteUser(4); sqlSession.commit(); sqlSession.close(); } }
6.分析错误
1.标签不要匹配错 com.tongda.dao.UserMapper;
2.resource绑定mapper,需要使用路径! com/tongda/dao/UserMapper 注意分隔符;
3.程序配置文件必须符合规范;
4.NullPointerException,没有注册到资源Utils中sqlSessionFactory作用域问题;
5.乱码问题
6.maven资源没有导出问题,pom.xml中在build中配置resources,来防止我们资源导出失败的问题
7.万能的Map
假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应该考虑使用Map!
UserMapper接口
//用万能Map插入用户
public void addUser2(Mapmap);
UserMapper.xml
insert into user (id,name,password) values (#{userid},#{username},#{userpassword})
测试UserDaoTest
@Test public void test3(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); HashMapmap = new HashMap (); map.put("userid",4); map.put("username","王虎"); map.put("userpassword",789); mapper.addUser2(map); //提交事务 sqlSession.commit(); //关闭资源 sqlSession.close(); }
Map传递参数,直接在sql中取出key即可! 【parameter=“map”】
对象传递参数,直接在sql中取出对象的属性即可! 【parameter=“Object”】
只有一个基本类型参数的情况下,可以直接在sql中取到
多个参数用Map , 或者注解!
7.模糊查询
模糊查询怎么写?
Java代码执行的时候,传递通配符% %
经常碰到这样的面试题目:#{}和${}的区别是什么?
网上的答案是:#{}是预编译处理,$ {}是字符串替换。
mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
mybatis在处理
使用 #{} 可以有效的防止SQL注入,提高系统安全性。
sql注入指的是用户输入 or 1=1等变量导致原sql语句逻辑发生了变化,使得可以直接进入数据库,而使用预编译的方法可以让sql语句只把传入的数据当做参数进行处理
而不会改变原有sql的逻辑,preparestatement和#{}都是把变量预编译,防止sql注入。
4、配置解析
1. 核心配置文件
-
mybatis-config.xml
-
Mybatis的配置文件包含了会深深影响MyBatis行为的设置和属性信息。
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
2. 环境配置 environments
MyBatis 可以配置成适应多种环境
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境

学会使用配置多套运行环境!
注意一些关键点:
- 默认使用的环境 ID(比如:default="development")。
- 每个 environment 元素定义的环境 ID(比如:id="development")。
- 事务管理器的配置(比如:type="JDBC")。
- 数据源的配置(比如:type="POOLED")。
默认环境和环境 ID 顾名思义。 环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。
MyBatis默认的事务管理器就是JDBC ,连接池:POOLED
3. 属性 properties
我们可以通过properties属性来实现引用配置文件
这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。【db.poperties】
1.编写一个配置文件
db.properties
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC username=root password=123456
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">
default="development">
1.可以直接引入外部文件
2.可以在其中增加一些属性配置
3.如果两个文件有同一个字段,优先使用外部配置文件的
注意点:核心配置文件书写标签配置顺序
properties放在最前面

4. 类型别名 typeAliases
-
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置.
-
意在降低冗余的全限定类名书写。