【知识】Mybatis-学习笔记

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 【知识】Mybatis-学习笔记

一、MyBatis简介


1.1 什么是Mybatis


  • MyBatis 是一款优秀的持久层框架
  • 它支持自定义 SQL、存储过程以及高级映射。
  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
  • MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
  • MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。


如何获得Mybatis?


  • maven仓库
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.2</version>
</dependency>



1.2 持久化


数据持久化


  • 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
  • 内存:断电即失
  • 数据库(JDBC),I/O文件持久化
  • 生活:冷藏、罐头


1.3 持久层


Dao层、Service层、Controller层


  • 完成持久化工作的代码块
  • 层的界限十分明显


1.4 为什么需要Mybatis?


  • 帮助程序员将数据存储到数据库中
  • 方便、传统的JDBC代码太复杂,Mybatis框架更容易上手
  • 简单易学、灵活
  • sql和代码的分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库
  • orm字段关系映射
  • 提供对象关系映射标签,支持对象关系组建维护
  • 提供xml标签,支持编写动态sql。
  • 最重要的一点:使用的人多


二、第一个Mybatis程序


思路:


1.创建父工程 引入mysql mybatis Junit 依赖

2.maven子工程 编写mybatis核心配置文件 mybatis-config.xml   连接数据库

3.untils层 pojo层 dao层

4.编写mybatis工具类  编写实体类

5.编写Mapper接口 以及对应UseMapper.xml配置文件

6.Junit测试


image.png


2.1 新建项目


建立mysql数据库

CREATE DATABASE MYBATIS;
USE MYBATIS;
CREATE TABLE user(
id INT(20) NOT NULL PRIMARY KEY,
name VARCHAR(30) DEFAULT NULL,
pwd VARCHAR(30) DEFAULT NULL
)ENGINE = INNODB DEFAULT CHARSET = utf8;
INSERT INTO user(id, name, pwd) VALUES 
(1, '孙孙孙', 2002),
(2, '铭铭铭', 1208),
(3, '孙不坚', 1234);

新建项目 1.新建一个普通的maven项目 2.删除src目录 3.导入maven依赖


将该工程当做父工程


<!--导入依赖-->
    <dependencies>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!--mybatis驱动-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.3</version>
        </dependency>
        <!--junit驱动-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

4.创建子工程


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">
<!--configuration核心配置文件-->
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="sm1208"/>
            </dataSource>
        </environment>
    </environments>
    <!--每一个Mapper.xml都需要Mybatis核心配置文件中注册!-->
    <mappers>
        <mapper resource="com/sun/dao/UserMapper.xml"/>
    </mappers>
</configuration>
  • 编写Mybatis的工具类
package com.sun.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;
import java.io.InputStream;
//sqlSessionFactory --> sqlSession
public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory = null;
    static {
        try {
            // 使用Mybatis 第一步:获取sqlSessionFactory对象
            String resource = "mybatis-config.xml";
            InputStream in = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 有了SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了
    // SqlSession  完全包含了面向数据库执行 SQL 命令所需要的所有方法
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}


2.3  编写代码


  • 实体类
package com.sun.pojo;
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 + '\'' +
                '}';
    }
}
  • Mapper接口
package com.sun.dao;
import com.sun.pojo.User;
import java.util.List;
public interface UserMapper {
    //查询所有的用户
    List<User> getUserList();
}
  • 接口实现类,由原来的UserDaoImp转变为一个Mapper配置文件,即UseMapper.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">
<!-- 命名空间 namespace=绑定一定是对应的Dao/Mapper接口 -->
<mapper namespace="com.sun.dao.UserMapper">
    <!-- select查询语句 -->
    <select id="getUserList" resultType="com.sun.pojo.User">
        select * from mybatis.user;
    </select>
</mapper>


2.4 测试


  • junit 测试
package com.sun.dao;
import com.sun.pojo.User;
import com.sun.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserMapperTest {
    @Test
    public void test(){
        // 第一步:获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        // 方式一:getMapper
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.getUserList();
        for (User user :
                userList) {
            System.out.println(user);
        }
        // 关闭 SqlSession
        sqlSession.close();
    }
}


2.5 常见问题


a 解决maven引入依赖资源过滤问题


<!-- 在build中配置resources,防止资源导出失败的问题 -->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>


b 解决xml文件中文字符集产生报错的问题


//引入依赖
<!--    <properties>-->
<!--        &lt;!&ndash; 设置默认编码 &ndash;&gt;-->
<!--        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>-->
<!--    </properties>-->


c 核心配置文件中注册 mappers


注意点:org.apache.ibatis.binding.BindingException: Type interface com.xulong.dao.UserDao is not known to the MapperRegistry.


<!--每一个Mapper.xml都需要Mybatis核心配置文件中注册!-->
    <mappers>
        <mapper resource="com/sun/dao/UserMapper.xml"/>
    </mappers>


三、CRUD


  • namespace中的包名要和 Dao/Mapper 接口的包名一致
  • 在xml文件sql
  • id : 就是对应的 namespace 中的方法名
  • resultType : Sql 语句执行的返回值
  • parameterType :参数类型
  • 编写接口 编写对应Mapper中的sql语句 编写测试
  • 增 删 改 需要提交事务 !


1. Select


//根据ID查询用户
User getUserByID(int id)
<select id="getUserByID" parameterType="int" resultType="com.sun.pojo.User">
  select * from mybatis.user where id = #{id};
</select>
@Test
public void getUserByID(){
  SqlSession sqlSession = MybatisUtils.getSqlSession();
  UserMapper mapper = sqlSession.getMapper(UserMapper.class);
  User user = mapper.getUserByID(1);
  System.out.println(user);
  sqlSession.close();
}


2. Insert


int addUser(User user);
<!-- 对象中的属性可以直接取出来 -->
<insert id="addUser" parameterType="com.sun.pojo.User">
  insert into mybatis.user (id, name, pwd) values (#{id}, #{name}, #{pwd});
</insert>
@Test
public void addUser(){
  SqlSession sqlSession = MybatisUtils.getSqlSession();
  UserMapper mapper = sqlSession.getMapper(UserMapper.class);
  User user = new User(4, "孙明明", "1324214");
  int result = mapper.addUser(user);
  if (result > 0){
    System.out.println("插入成功!");
  }
  //提交事务
  sqlSession.commit();
  sqlSession.close();
}


3. Updata


//修改用户
int updateUser(User user);
<update id="updateUser" parameterType="com.sun.pojo.User">
  update mybatis.user set name = #{name}, pwd = #{pwd} where id = #{id};
</update>
@Test
    public void updateUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User(5, "旺财", "14432434");
        mapper.updateUser(user);
        int result = mapper.updateUser(user);
        if (result > 0){
            System.out.println("修改成功!");
        }
        sqlSession.commit();
        sqlSession.close();
    }


4. Delete


//删除用户
int deleteUser(int id);
<delete id="deleteUser" parameterType="int">
  delete from mybatis.user where id = #{id};
</delete>
@Test
public void deleteUser(){
  SqlSession sqlSession = MybatisUtils.getSqlSession();
  UserMapper mapper = sqlSession.getMapper(UserMapper.class);
  mapper.deleteUser(4);
  sqlSession.commit();
  sqlSession.close();
}


5. Map


假设我们的实体类,数据库中的表、字段或者参数过多,我们应当考虑使用Map。

//万能的Map
int addUser1(Map<String, Object> map);
<!-- 对象中的属性可以直接取出来    传递Map中的key -->
<insert id="addUser1" parameterType="Map">
  insert into mybatis.user (id, name, pwd) values (#{userid}, #{username}, #{password});
</insert>
@Test
public void addUser1(){
  SqlSession sqlSession = MybatisUtils.getSqlSession();
  UserMapper mapper = sqlSession.getMapper(UserMapper.class);
  Map<String, Object> map = new HashMap<>();
  map.put("userid", 5);
  map.put("username", "赵六");
  map.put("password", "144324324");
  mapper.addUser1(map);
  sqlSession.close();
}

Map传递参数,直接在sql中取出key即可【parameterType=“Map”】 对象传递参数,直接在sql中取对象的属性即可【parameterType=“Object”】 只有一个基本类型参数的情况下,可以直接在sql中取到,不需要parameterType的设置 多个参数用Map,或者注解


四、核心配置解析


mybatis-config.xml配置解析


image.png


1.  属性 (properties)


xml里属性都是可外部配置且可动态替换的,我们可以通过properties属性来实现引用配置文件。


  • 编写一个配置文件 db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC
username=root
password=sm1208
  • 在核心配置文件中引入
  • 直接引入外部文件
<!-- 引入外部配置文件 -->
<properties resource="db.properties"> </properties>
  • 可以在其中增加一些属性配置
<!-- 引入外部配置文件 -->
<properties resource="db.properties">
  <property name="username" value="root"/>
  <property name="password" value="sm1208"/>
</properties>
  • 如果两个文件有同一个字段,优先使用外部配置文件


2. 设置 (settings)



image.png

image.png

image.png


3. 类型别名(typeAliases)


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


  • 第一种配置方式 ,User 可以用在任何使用 com.sun.pojo.User 的地方使用。
<typeAliases>
  <typeAlias alias="User" type="com.sun.pojo.User"/>
</typeAliases>
  • 第二种配置方式,指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,例如: 扫描实体类pojo的包,它的默认别名就为这个类的类名User。
<typeAliases>
  <package name="com.sun.pojo"/>
</typeAliases>

在实体类比较少的情况,推荐使用第一种方式,如果实体类多的情况下,建议使用第二种方式,第一种可以DIY别名,第二种则不行,如果想实现第二种的DIY,在第二种配置方式的基础上还需要在实体类上增加注解:

import org.apache.ibatis.type.Alias;
@Alias("hello")
public class User {
}


4. 类型处理器(typeHandlers)


5. 对象工厂(objectFactory)


6. 插件(plugins)


7. 环境配置(environments)


MyBatis 可以配置成适应多种环境,尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。


  • 默认使用的环境 ID(比如:default="development")。
  • 每个 environment 元素定义的环境 ID(比如:id="development")。
  • 事务管理器的配置(比如:type="JDBC")。
  • 数据源的配置(比如:type="POOLED")。

环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。


8. 数据库厂商标识(databaseIdProvider)


9. 映射器(mappers)


MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件,**即映射器注册问题MapperRegistry:注册绑定我们的Mapper文件。**你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:/// 形式的 URL),或类名和包名等。例如:


  • 【推荐使用】
<!-- 使用相对于类路径的资源引用  --> 
<mappers>
  <mapper resource="com/sun/dao/UserMapper.xml"/>
</mappers>
  • 使用class文件进行绑定
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="com.sun.dao.UserMapper"/>
</mappers>
  • 接口和其对应的Mapper配置文件必须同名
  • 接口和其对应的Mapper配置文件必须在同一个包下
  • 使用扫描包进行注入绑定
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="com.sun.dao"/>
</mappers>


  • 接口和其对应的Mapper配置文件必须同名
  • 接口和其对应的Mapper配置文件必须在同一个包下


10. 生命周期和作用域


五、使用注解开发


1. 面向接口编程


大家之前都学习过面向对象编程,也学习过接口,但在真正的开发中,很多时候我们会选择面向接口编程。 根本原因:解耦,可拓展,提高复用,分层开发中,上层不用管具体的实现,大家都遵守共同的标准,使得开发变得容易,规范性更好。 在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协助完成的。在这种情况下,各个对象内部是如何实现自己的,对系统设计人员来讲就不那么重要了。 而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大道各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是按照这种思想来编程。

关于接口的理解

  • 接口从更深层次的理解,应是定义(规范、约束)与实现(名实分离的原则)的分离。
  • 接口的本身反映了系统设计人员对系统的抽象理解。
  • 接口应有两种
  • 第一类是对一个个体的抽象,它可对应为一个抽象体(abstract class)
  • 第二类是对一个个体某一方面的抽象,即形成一个抽象面(interface)
  • 一个体可能有多个抽象面,抽象体和抽象面是有区别的。

三个面向区别

  • 面向向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法。
  • 面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现。
  • 接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题,更多的体现就是对系统整体的架构。


2. 使用注解开发


  • 注解在接口上实现
@Select("select * from user")
List<User> get
  • 在核心配置文件中绑定接口
<!-- 绑定接口 -->
<mappers>
  <mapper class="com.fj.dao.UserMapper"/>
</mappers>
  • 测试
@Test
public void test(){
  SqlSession sqlSession = MybatisUtils.getSqlSession();
  //底层主要应用反射
  UserMapper mapper = sqlSession.getMapper(UserMapper.class);
  List<User> users = mapper.getUsers();
  for (User user : users){
    System.out.println(user);
  }
  sqlSession.close();
}

本质:反射机制实现底层:动态代理

Mybatis详细执行流程


image.png

image.png

image.png



3.注解-CRUD


  • 我们可以在工具类创建的时候实现自动提交事务
public static SqlSession getSqlSession(){
  return sqlSessionFactory.openSession(true);
}
  • 编写接口,添加注解
@Select("select * from user")
List<User> getUsers();
// 方法中如果有多个参数,那么每一个参数前都必须加上@Param("")
@Select("select * from user where id = #{id}")
User getUserByID(@Param("id") int id);
//    User getUserByID(@Param("id") int id, @Param("name") String name);
@Insert("insert into user (id, name, pwd) values (#{id}, #{name}, #{password})")
int addUser(User user);
@Update("update user set name = #{name}, pwd = #{password} where id = #{id}")
int updateUser(User user);
@Delete("delete from user where id = #{id}")
int deleteUser(@Param("id") int id);
  • 测试类
  • 【注意,我们必须要将接口绑定到核心配置文件mybatis-config.xml文件中】
<!-- 绑定接口 -->
<mappers>
  <mapper class="com.sun.dao.UserMapper"/>
</mappers>



相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
XML Java 数据库连接
java202304java学习笔记第六十五天-ssm-声明式控制-基于xml的声明式配置-mybatis的概述2
java202304java学习笔记第六十五天-ssm-声明式控制-基于xml的声明式配置-mybatis的概述2
56 0
java202304java学习笔记第六十六天-ssm-mybatis-接口代理方法实现
java202304java学习笔记第六十六天-ssm-mybatis-接口代理方法实现
42 0
|
7月前
|
SQL Java 关系型数据库
MyBatisPlus学习笔记(SpringBoot版)
MyBatisPlus学习笔记(SpringBoot版)
502 0
|
SQL Java 关系型数据库
|
SQL Java 关系型数据库
java202304java学习笔记第六十六天-ssm-mybatis的dao层实现1
java202304java学习笔记第六十六天-ssm-mybatis的dao层实现1
36 0
java202304java学习笔记第六十六天-ssm-mybatis中dao层实现-动态sql-foreach之2
java202304java学习笔记第六十六天-ssm-mybatis中dao层实现-动态sql-foreach之2
59 0
java202304java学习笔记第六十六天-ssm-mybatis中dao层实现-动态sql-if之1
java202304java学习笔记第六十六天-ssm-mybatis中dao层实现-动态sql-if之1
37 0