• ​​​​MyBatis友人帐之基础入门


    一、简介

    1.1什么是MyBatis

    MyBatis 是一个开源的、轻量级的数据持久层框架,它可以简化 JDBC 的操作,让开发者只需要关注 SQL 语句本身,而不用处理加载驱动、创建连接、创建语句等繁琐的过程。

    MyBatis 支持自定义 SQL、存储过程和高级映射,可以通过 XML 或注解来配置和映射原始类型、接口和 Java POJO(普通老式 Java 对象)为数据库中的记录。MyBatis 也提供了动态 SQL、类型别名、插件、缓存等功能,使得数据持久化更加灵活和高效

    1.2持久化

    持久化是将程序数据在持久状态和瞬时状态间转换的机制。

    • 即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中、XML数据文件中等等。

    • JDBC就是一种持久化机制。文件IO也是一种持久化机制。

    • 在生活中 : 将鲜肉冷藏,吃的时候再解冻的方法也是。将水果做成罐头的方法也是。

    为什么需要持久化服务呢?那是由于内存本身的缺陷引起的

    • 内存断电后数据会丢失,但有一些对象是无论如何都不能丢失的,比如银行账号等,遗憾的是,人们还无法保证内存永不掉电。

    • 内存过于昂贵,与硬盘、光盘等外存相比,内存的价格要高2~3个数量级,而且维持成本也高,至少需要一直供电吧。所以即使对象不需要永久保存,也会因为内存的容量限制不能一直呆在内存中,需要持久化来缓存到外存。

    1.3持久层

    什么是持久层?

    • 完成持久化工作的代码块 .  ---->  dao层 【DAO (Data Access Object)  数据访问对象】

    • 大多数情况下特别是企业级应用,数据持久化往往也就意味着将内存中的数据保存到磁盘上加以固化,而持久化的实现过程则大多通过各种关系数据库来完成。

    • 不过这里有一个字需要特别强调,也就是所谓的“层”。对于应用系统而言,数据持久功能大多是必不可少的组成部分。也就是说,我们的系统中,已经天然的具备了“持久层”概念?也许是,但也许实际情况并非如此。之所以要独立出一个“持久层”的概念,而不是“持久模块”,“持久单元”,也就意味着,我们的系统架构中,应该有一个相对独立的逻辑层面,专注于数据持久化逻辑的实现.

    • 与系统其他部分相对而言,这个层面应该具有一个较为清晰和严格的逻辑边界。【说白了就是用来操作数据库存在的!】

    1.4Lombok介绍

    Lombok 是一个 Java 库,可以通过注解的方式来简化 Java 代码,提高开发效率。它可以自动生成 getter、setter、equals、hashCode、toString 等方法,也可以自动化日志变量,还有一些其他的功能。Lombok 不仅是一个依赖 jar 包,也是一个 IDE 插件,它可以在编译时修改 AST(抽象语法树),从而改变字节码生成。

    idea默认已集成Lombok

    1.5 MyBatis-Plus

    1.6MyBatis的优点

    • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件就可以了,易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。

    • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。

    • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。

    • 提供xml标签,支持编写动态sql。

     二、环境配置与测试

    2.1环境配置

    1. <dependencies>
    2. <dependency>
    3. <groupId>org.mybatisgroupId>
    4. <artifactId>mybatisartifactId>
    5. <version>3.5.2version>
    6. dependency>
    7. <dependency>
    8. <groupId>mysqlgroupId>
    9. <artifactId>mysql-connector-javaartifactId>
    10. <version>5.1.47version>
    11. dependency>
    12. <dependency>
    13. <groupId>junitgroupId>
    14. <artifactId>junitartifactId>
    15. <version>4.12version>
    16. dependency>
    17. dependencies>

    可能出现问题说明:Maven静态资源过滤问题

    1. <resources>
    2. <resource>
    3. <directory>src/main/javadirectory>
    4. <includes>
    5. <include>**/*.propertiesinclude>
    6. <include>**/*.xmlinclude>
    7. includes>
    8. <filtering>falsefiltering>
    9. resource>
    10. <resource>
    11. <directory>src/main/resourcesdirectory>
    12. <includes>
    13. <include>**/*.propertiesinclude>
    14. <include>**/*.xmlinclude>
    15. includes>
    16. <filtering>falsefiltering>
    17. resource>
    18. resources>

    2.2编写MyBatis核心配置文件

    1. "1.0" encoding="UTF-8" ?>
    2. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    3. "http://mybatis.org/dtd/mybatis-3-config.dtd">
    4. default="development">
    5. "development">
    6. "JDBC"/>
    7. "POOLED">
    8. "driver" value="com.mysql.jdbc.Driver"/>
    9. "url" value="jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT"/>
    10. "username" value="root"/>
    11. "password" value="b123456"/>
    12. "com/yanyu/dao/userMapper.xml"/>

    在使用mybatis连接MySQL数据库时,遇到这个问题:

    com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

    解决方案

    在mybatis-config.xml配置文件中,修改useSSL属性为false

    原因分析: SSL(Secure Sockets Layer 安全套接字协议),在mysql进行连接的时候,如果mysql的版本是5.7之后的版本必须要加上useSSL=false,mysql5.7以及之前的版本则不用进行添加useSSL=false,会默认为false,一般情况下都是使用useSSL=false,useSSL=true是进行安全验证,一般通过证书或者令牌什么的,useSSL=false就是通过账号密码进行连接。

    2.3编写MyBatis工具类

    1. package com.yanyu.utils;
    2. import org.apache.ibatis.io.Resources;
    3. import org.apache.ibatis.session.SqlSession;
    4. import org.apache.ibatis.session.SqlSessionFactory;
    5. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    6. import java.io.IOException;
    7. import java.io.InputStream;
    8. public class MybatisUtils {
    9. private static SqlSessionFactory sqlSessionFactory;
    10. static {
    11. try {
    12. String resource = "mybatis-config.xml";
    13. InputStream inputStream = Resources.getResourceAsStream(resource);
    14. sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    15. } catch (IOException e) {
    16. e.printStackTrace();
    17. }
    18. }
    19. //获取SqlSession连接
    20. public static SqlSession getSession(){
    21. return sqlSessionFactory.openSession();
    22. }
    23. }

     2.4创建实体类

    1. package com.yanyu.pojo;
    2. import lombok.*;
    3. @Getter
    4. @Setter
    5. @ToString
    6. @NoArgsConstructor
    7. @AllArgsConstructor
    8. public class User {
    9. private int id; //id
    10. private String name; //姓名
    11. private String pwd; //密码
    12. //构造,有参,无参
    13. //set/get
    14. //toString()
    15. }

    2.5编写Mapper接口类

    1. package com.yanyu.dao;
    2. import com.yanyu.pojo.User;
    3. import java.util.List;
    4. public interface UserMapper {
    5. List selectUser();
    6. }

    2.6编写Mapper.xml配置文件

    1. "1.0" encoding="UTF-8" ?>
    2. mapper
    3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="com.yanyu.dao.UserMapper">
    6. <select id="selectUser" resultType="com.yanyu.pojo.User">
    7. select * from user1
    8. select>
    9. mapper>

    2.7测试

    1. package com.yanyu.dao;
    2. import com.yanyu.pojo.User;
    3. import com.yanyu.utils.MybatisUtils;
    4. import org.apache.ibatis.session.SqlSession;
    5. import org.junit.Test;
    6. import java.util.List;
    7. public class MyTest {
    8. @Test
    9. public void selectUser() {
    10. SqlSession session = MybatisUtils.getSession();
    11. //方法一:
    12. //List users = session.selectList("com.kuang.mapper.UserMapper.selectUser");
    13. //方法二:
    14. UserMapper mapper = session.getMapper(UserMapper.class);
    15. List users = mapper.selectUser();
    16. for (User user: users){
    17. System.out.println(user);
    18. }
    19. session.close();
    20. }
    21. }

    三、增删改查

    3.1Mapper.xml中的命名空间及命名解析

    Mybatis命名空间是一个用来区分不同映射文件中的SQL语句的标识符。命名空间可以是任意的字符串,通常是映射文件对应的接口类的全限定名,例如com.jianglei.example.bean.UserMapper。命名空间的作用有两个:

    • 一是可以避免SQL语句的ID冲突,因为每个SQL语句都是在命名空间中唯一的,而不是全局唯一的。例如,两个不同的映射文件中都可以有一个ID为findById的SQL语句,只要它们的命名空间不同即可。
    • 二是可以实现接口绑定,即让Mybatis自动根据接口方法生成代理对象,执行对应的SQL语句。这样可以省去手动编写代码,调用SqlSession的方法,提高开发效率和代码可读性。

    3.2Select

    选择,查询语句;
    ●id:就是对应的namespace中的方法名;
    ●resultType: Sq|语句执行的返回值!
    ●parameterType :参数类型! .

    需求:根据id查询用户

    1、在UserMapper中添加对应方法

    1. public interface UserMapper {
    2.    //查询全部用户
    3.    List selectUser();
    4.    //根据id查询用户
    5.    User selectUserById(int id);
    6. }

    2、在UserMapper.xml中添加Select语句

    1. "selectUserById" resultType="com.yanyu.pojo.User">
    2. select * from user where id = #{id}

    3、测试类中测试

    1. @Test
    2. public void tsetSelectUserById() {
    3.    SqlSession session = MybatisUtils.getSession();  //获取SqlSession连接
    4.    UserMapper mapper = session.getMapper(UserMapper.class);
    5.    User user = mapper.selectUserById(1);
    6.    System.out.println(user);
    7.    session.close();
    8. }

    3.3insert

    我们一般使用insert标签进行插入操作,它的配置和select标签差不多!

    需求:给数据库增加一个用户

    1、在UserMapper接口中添加对应的方法

    1. //添加一个用户
    2. int addUser(User user);

    2、在UserMapper.xml中添加insert语句

    1. <insert id="addUser" parameterType="com.ysnyu.pojo.User">
    2. insert into user1 (id,name,pwd) values (#{id},#{name},#{pwd})
    3. insert>

    3、测试

    1. @Test
    2. public void testAddUser() {
    3. SqlSession session = MybatisUtils.getSession();
    4. UserMapper mapper = session.getMapper(UserMapper.class);
    5. User user = new User(4,"李四","zxcvbn");
    6. int i = mapper.addUser(user);
    7. System.out.println(i);
    8. session.commit(); //提交事务,重点!不写的话不会提交到数据库
    9. session.close();
    10. }

    注意点:增、删、改操作需要提交事务!

    ​​​​​​​3.4update

    需求:修改用户的信息

    1、同理,编写接口方法

    1. //修改一个用户
    2. int updateUser(User user);

    2、编写对应的配置文件SQL

    1. <update id="updateUser" parameterType="com.yanyu.pojo.User">
    2. update user1 set name=#{name},pwd=#{pwd} where id = #{id}
    3. update>

    3、测试

    1. @Test
    2. public void testUpdateUser() {
    3. SqlSession session = MybatisUtils.getSession();
    4. UserMapper mapper = session.getMapper(UserMapper.class);
    5. User user = mapper.selectUserById(1);
    6. user.setPwd("asdfgh");
    7. int i = mapper.updateUser(user);
    8. System.out.println(i);
    9. session.commit(); //提交事务,重点!不写的话不会提交到数据库
    10. session.close();
    11. }

    3.5delete

    我们一般使用delete标签进行删除操作,它的配置和select标签差不多!

    需求:根据id删除一个用户

    1、同理,编写接口方法

    1. //根据id删除用户
    2. int deleteUser(int id);

    2、编写对应的配置文件SQL

    1. "deleteUser" parameterType="int">
    2. delete from user1 where id = #{id}

    3、测试

    1. @Test
    2. public void testDeleteUser() {
    3. SqlSession session = MybatisUtils.getSession();
    4. UserMapper mapper = session.getMapper(UserMapper.class);
    5. int i = mapper.deleteUser(4);
    6. System.out.println(i);
    7. session.commit(); //提交事务,重点!不写的话不会提交到数据库
    8. session.close();
    9. }

    3.6总结

    小结:

    • 所有的增删改操作都需要提交事务!

    • 接口所有的普通参数,尽量都写上@Param参数,尤其是多个参数时,必须写上!

    • 有时候根据业务的需求,可以考虑使用map传递参数!

    • 为了规范操作,在SQL的配置文件中,我们尽量将Parameter参数和resultType都写上!

    3.7map

    1、在接口方法中,参数直接传递Map;

    User selectUserByNP2(Map map);

    2、编写sql语句的时候,需要传递参数类型,参数类型为map

    1. "selectUserByNP2" parameterType="map" resultType="com.kuang.pojo.User">
    2. select * from user where name = #{username} and pwd = #{pwd}

    3、在使用方法的时候,Map的 key 为 sql中取的值即可,没有顺序要求!

    1. Map map = new HashMap();
    2. map.put("username","小明");
    3. map.put("pwd","123456");
    4. User user = mapper.selectUserByNP2(map);

    3.8模糊查询like语句

    1、在接口方法中,参数直接传递Map;

    List getUserLike(String value);

    2、编写sql语句的时候,需要传递参数类型

    3.测试

    1. @Test
    2. public void testgetUserLike() {
    3. SqlSession session = MybatisUtils.getSession(); //获取SqlSession连接
    4. UserMapper mapper = session.getMapper(UserMapper.class);
    5. List users = mapper.getUserLike("%李%");
    6. for (User user: users){
    7. System.out.println(user);
    8. }
    9. session.close();
    10. }

    四、配置解析

    4.1核心配置文件

    核心配置文件

    • mybatis-config.xml 系统核心配置文件

    • MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。

    • 能配置的内容如下:

    1. configuration(配置)
    2. properties(属性)
    3. settings(设置)
    4. typeAliases(类型别名)
    5. typeHandlers(类型处理器)
    6. objectFactory(对象工厂)
    7. plugins(插件)
    8. environments(环境配置)
    9. environment(环境变量)
    10. transactionManager(事务管理器)
    11. dataSource(数据源)
    12. databaseIdProvider(数据库厂商标识)
    13. mappers(映射器)

    4.2environments元素

    1. default="development">
    2. "development">
    3. "JDBC">
    4. "..." value="..."/>
    5. "POOLED">
    6. "driver" value="${driver}"/>
    7. "url" value="${url}"/>
    8. "username" value="${username}"/>
    9. "password" value="${password}"/>
    • 配置MyBatis的多套运行环境,将SQL映射到多个不同的数据库上,必须指定其中一个为默认运行环境(通过default指定)

    • 子元素节点:environment

      • dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。

      • 数据源是必须配置的。

      • 有三种内建的数据源类型

        type="[UNPOOLED|POOLED|JNDI]"
      • unpooled:这个数据源的实现只是每次被请求时打开和关闭连接。

      • pooled:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来 , 这是一种使得并发 Web 应用快速响应请求的流行处理方式。

      • jndi:这个数据源的实现是为了能在如 Spring 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。

      • 数据源也有很多第三方的实现,比如dbcp,c3p0,druid等等....

      • 详情:点击查看官方文档

      • 这两种事务管理器类型都不需要设置任何属性。

      • 具体的一套环境,通过设置id进行区别,id保证唯一!

      • 子元素节点:transactionManager - [ 事务管理器 ]

    1. "[ JDBC | MANAGED ]"/>

     4.3Properties优化

    数据库这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。具体的官方文档

    我们来优化我们的配置文件

    第一步 ; 在资源目录下新建一个db.properties

    1. driver=com.mysql.jdbc.Driver
    2. url=jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
    3. username=root
    4. password=b123456

    第二步 : 将文件导入properties 配置文件

    1.    
    2.    "db.properties"/>
    3.    default="development">
    4.        "development">
    5.            "JDBC"/>
    6.            "POOLED">
    7.                "driver" value="${driver}"/>
    8.                "url" value="${url}"/>
    9.                "username" value="${username}"/>
    10.                "password" value="${password}"/>
    11.            
    12.        
    13.    
    14.    
    15.        "mapper/UserMapper.xml"/>
    16.    

    ●可以直接引入外部文件
    ●可以在其中增加一些属性配置
    ●如果两个文件有同一个字段,优先使用外部配置文件的!|

    4.4别名优化

    类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余

    1. "com.yanyu.pojo.User" alias="User"/>

    当这样配置时,User可以用在任何使用com.yanyu.pojo.User的地方。

    也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean

    1. <package name="com.yanyu.pojo"/>

    每一个在包 com.kuang.pojo 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。

    若有注解,则别名为其注解值。见下面的例子:

    1. @Alias("user")
    2. public class User {
    3. ...
    4. }

    4.5设置

    • 设置(settings)相关 => 查看帮助文档

      • 懒加载

      • 日志实现

      • 缓存开启关闭

    4.6作用域(Scope)和生命周期

    ​​​​​​​

    作用域理解

    • SqlSessionFactoryBuilder 的作用在于创建 SqlSessionFactory,创建成功后,SqlSessionFactoryBuilder 就失去了作用,所以它只能存在于创建 SqlSessionFactory 的方法中,而不要让其长期存在。因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。

    • SqlSessionFactory 可以被认为是一个数据库连接池,它的作用是创建 SqlSession 接口对象。因为 MyBatis 的本质就是 Java 对数据库的操作,所以 SqlSessionFactory 的生命周期存在于整个 MyBatis 的应用之中,所以一旦创建了 SqlSessionFactory,就要长期保存它,直至不再使用 MyBatis 应用,所以可以认为 SqlSessionFactory 的生命周期就等同于 MyBatis 的应用周期。

    • 由于 SqlSessionFactory 是一个对数据库的连接池,所以它占据着数据库的连接资源。如果创建多个 SqlSessionFactory,那么就存在多个数据库连接池,这样不利于对数据库资源的控制,也会导致数据库连接资源被消耗光,出现系统宕机等情况,所以尽量避免发生这样的情况。

    • 因此在一般的应用中我们往往希望 SqlSessionFactory 作为一个单例,让它在应用中被共享。所以说 SqlSessionFactory 的最佳作用域是应用作用域。

    • 如果说 SqlSessionFactory 相当于数据库连接池,那么 SqlSession 就相当于一个数据库连接(Connection 对象),你可以在一个事务里面执行多条 SQL,然后通过它的 commit、rollback 等方法,提交或者回滚事务。所以它应该存活在一个业务请求中,处理完整个请求后,应该关闭这条连接,让它归还给 SqlSessionFactory,否则数据库资源就很快被耗费精光,系统就会瘫痪,所以用 try...catch...finally... 语句来保证其正确关闭。

    • 所以 SqlSession 的最佳的作用域是请求或方法作用域。

  • 相关阅读:
    【统计、图形和样本量软件】上海道宁为您提高强大的统计分析、图形和样本量工具
    STM32 | 库函数与寄存器开发区别及LED等和按键源码(第三天)
    联想拯救者电脑数据恢复方法,适用于未备份者
    QGIS安装(以Windows系统为例)
    (附源码)springboot投稿和稿件处理系统 毕业设计 201458
    C++11:函数对象、闭包和Lambda
    Centos7上使用yum安装mysql8.x
    二分法之旋转数组
    Redis之String类型
    软件测试用例设计练习
  • 原文地址:https://blog.csdn.net/qq_62377885/article/details/133026875