• MyBatis --学习笔记


    什么是MyBatis?

    • 用来访问操作数据库的一个框架

    使用MyBatis的准备工作:

    创建spring boot工程的时候点上mybatis的起步依赖和mysql的驱动包

    图示:

    准备好对应数据的实体类

    在Mybatis中要连接数据库,需要以下4个参数配置:

    • MySQL驱动类

    • 登录名

    • 密码

    • 数据库连接字符串

    那怎么获得这四个参数的值呢?
    登录名和密码就是登录数据库的账号和密码
    mysql驱动类和mysql数据库连接字符串可以在新建数据库源的界面找到
    图示:

    得到四个值后直接在springboot项目中的application.properties文件按下面的格式写入就行了

    1. #驱动类名称
    2. spring.datasource.driver-class-name=驱动类名称
    3. #数据库连接字符串
    4. spring.datasource.url=数据库连接字符串
    5. #连接数据库的用户名
    6. spring.datasource.username=连接数据库的用户名
    7. #连接数据库的密码
    8. spring.datasource.password=连接数据库的密码

    使用MyBatis访问数据库: 

    基础访问

    首先在启动类所在包下创建一个mapper包(持久层,代替了Dao),然后在里面创建一个xxxMapper接口(Mybatis的持久层接口规范一般都叫 XxxMapper )

    图示:

    在接口类名上打上@Mapper注解,在接口里面定义一个个方法用来访问数据,然后在每个方法上打上对应的注解,在注解的属性中写上对应的sql语句,光说可能比较抽象,上图:

     如果需要sql语句联想,可以选中sql语句部分-->右击-->显示上下文操作-->语言注入设置-->Mysql

    然后就会出现sql语句联想了,如果对应的表名字段名之类的没联想出来,可能是IDEA没有连接该数据库

    参数占位符

     在实际开发中,大部分情况下sql语句都不应该是写死的,不可变的,而应该是配合变量达到根据要求查询的效果,所以参数占位符便来了:

    在Mybatis中提供的参数占位符有两种:${...} 、#{...}

    • #{...}

      • 执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值

      • 使用时机:参数传递,都使用#{…}

    • ${...}

      • 拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题

      • 使用时机:如果对表名、列表进行动态设置时使用

    图示:

    如图,根据传入的id值删除部门

    在实际开发中,推荐使用#{...}而不是${...},因为#{...}不仅效率更高,还更安全,可以防sql注入

    效率高:预编译SQL,编译一次之后会将编译后的SQL语句缓存起来,后面再次执行这条语句时,不会再次编译。(只是输入的参数不同)

    sql注入:假如使用${...},用户可以直接输入譬如  'or'1'='1 之类的密码,拼接之后就会是

    select * from emp where username = #{username} and password = '' or '1'='1';

    毫无疑问这是非常糟糕的,根本不需要正确的密码直接就登录了

    在使用参数占位符时也可以直接对应对象类型的形参的成员属性,比如

    1. //修改员工信息
    2. @Update("update emp set username = #{username}, name = #{name}, gender = #{gender}, image = #{image}," +
    3. " job = #{job},dept_id = #{deptId}, entrydate = #{entrydate}, update_time = #{updateTime} where id = #{id}")
    4. void update(Emp emp);

     前提是有在emp对象中设置对应的属性值

    主键返回

    如果在数据添加成功后,需要获取插入数据库数据的主键——

    可以在Mapper接口中的方法上添加一个Options注解,并在注解中指定属useGeneratedKeys=true和keyProperty="实体类属性名"

    1. //修改员工信息
    2. //会自动将生成的主键值,赋值给emp对象的id属性
    3. @Options(useGeneratedKeys = true,keyProperty = "id")
    4. @Update("update emp set username = #{username}, name = #{name}, gender = #{gender}, image = #{image}," +
    5. " job = #{job},dept_id = #{deptId}, entrydate = #{entrydate}, update_time = #{updateTime} where id = #{id}")
    6. void update(Emp emp);

     数据封装

    一般在java中命名变量名 都是使用驼峰命名法,而在数据库中一般是使用_分隔,例如部门id的属性值在java中可能习惯命名为deptId而在数据库中习惯命名为dept_id,此时就会出现对象属性名与数据库字段名不匹配的情况

    可开启驼峰命名 解决

    驼峰命名:如果字段名与属性名符合驼峰命名规则,mybatis会自动通过驼峰命名规则映射

    驼峰命名规则: abc_xyz => abcXyz

    • 表中字段名:abc_xyz

    • 类中属性名:abcXyz

    直接在application.properties中添加如下属性就可以了

    mybatis.configuration.map-underscore-to-camel-case=true

    要使用驼峰命名前提是 实体类的属性 与 数据库表中的字段名严格遵守驼峰命名 

    Mybatis的XML配置文件

    如果要实现比较复杂的sql语句,使用注解就会让代码显得比较臃肿,而且不太方便,此时就可以使用xml来配置映射语句,也就是将sql语句编写在xml配置文件中

    在Mybatis中使用XML映射文件方式开发,需要符合一定的规范:

    1. XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在同名的包下(同包同名)

    2. XML映射文件的namespace属性为Mapper接口全限定名一致

    3. XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致

    关于第一点(配置文件都是放在resources目录下):

    关于第二点:

    直接按住ctrl单击接口名就可以得知接口的全限定名

    关于第三点:

    编写XML配置文件: 

    xml映射文件中上面那一串dtd约束,直接从mybatis官网复制即可

    1. "1.0" encoding="UTF-8" ?>
    2. mapper
    3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4. "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="">
    6. mapper>

    然后在mapper标签中写上对应标签,在其中写上sql语句就ok了

    图示:

    譬如上图select查询就是映射的com.zeyu.mapper下的EmpMapper接口中的list方法,其list方法的返回值类型为com.zeyu.pojo下的Emp实体类,通过这三个属性值,就可以将编写的sql定位到一个方法上,而在xml中也有一种特殊的语法,那就是动态sql——

    动态sql

    ...... 标签:

            如果test中的表达式为真,则执行if标签中的语句,否则不执行

    图示:

    聪明的小伙伴肯定发现了,假如第一个if为假,其它if为真,那直接拼接不就成了

     select * from emp where and gender = #{gender} and entrydate between #{begin} and #{end} order by update_time desc  

    where 后面怎么可以直接写and呢?!

    所以为了解决这个情况,有了where标签

    ...... 标签:

            只会在子元素有内容的情况下才会插入where,且自动去除多余的and或or

    图示:

             

    同样的道理,在我们动态执行修改语句时,也可能出现最后多出一个逗号的情况

    图示:

    聪明的小伙伴肯定又想到了,假如最后一个if没有执行,那where前面就多出了一个逗号

    自然而然的,set标签出现了

    ......:

            动态的在SQL语句中插入set关键字,并会删掉多余的逗号

    图示:

    假如传入的参数是一个数组或列表,比如要根据id批量删除员工,此时就可以使用

    .......

    图示:

    减少重复sql的编写——sql&include

    使用sql标签将重复语句打包,id值为该sql片段的名字

    使用include引入打包好的sql片段,refid值为要引入的sql片段的名字

    JDBC

    什么是JDBC呢?

    JDBC: ( Java DataBase Connectivity ),就是使用Java语言操作关系型数据库的一套API

    Mybatis框架,就是对原始的JDBC程序的封装

    本质:

    • sun公司官方定义的一套操作所有关系型数据库的规范,即接口。

    • 各个数据库厂商去实现这套接口,提供数据库驱动jar包。

    • 我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

    原始的JDBC程序是操作数据库的操作步骤如下:

    1. import com.itheima.pojo.User;
    2. import org.junit.jupiter.api.Test;
    3. import java.sql.Connection;
    4. import java.sql.DriverManager;
    5. import java.sql.ResultSet;
    6. import java.sql.Statement;
    7. import java.util.ArrayList;
    8. import java.util.List;
    9. public class JdbcTest {
    10. @Test
    11. public void testJdbc() throws Exception {
    12. //1. 注册驱动
    13. Class.forName("com.mysql.cj.jdbc.Driver");
    14. //2. 获取数据库连接
    15. String url="jdbc:mysql://127.0.0.1:3306/mybatis";
    16. String username = "root";
    17. String password = "1234";
    18. Connection connection = DriverManager.getConnection(url, username, password);
    19. //3. 执行SQL
    20. Statement statement = connection.createStatement(); //操作SQL的对象
    21. String sql="select id,name,age,gender,phone from user";
    22. ResultSet rs = statement.executeQuery(sql);//SQL查询结果会封装在ResultSet对象中
    23. List<User> userList = new ArrayList<>();//集合对象(用于存储User对象)
    24. //4. 处理SQL执行结果
    25. while (rs.next()){
    26. //取出一行记录中id、name、age、gender、phone下的数据
    27. int id = rs.getInt("id");
    28. String name = rs.getString("name");
    29. short age = rs.getShort("age");
    30. short gender = rs.getShort("gender");
    31. String phone = rs.getString("phone");
    32. //把一行记录中的数据,封装到User对象中
    33. User user = new User(id,name,age,gender,phone);
    34. userList.add(user);//User对象添加到集合
    35. }
    36. //5. 释放资源
    37. statement.close();
    38. connection.close();
    39. rs.close();
    40. //遍历集合
    41. for (User user : userList) {
    42. System.out.println(user);
    43. }
    44. }
    45. }

    DriverManager(类):数据库驱动管理类。

    • 作用:

      1. 注册驱动

      2. 创建java代码和数据库之间的连接,即获取Connection对象

    Connection(接口):建立数据库连接的对象

    • 作用:用于建立java程序和数据库之间的连接

    Statement(接口): 数据库操作对象(执行SQL语句的对象)。

    • 作用:用于向数据库发送sql语句

    ResultSet(接口):结果集对象(一张虚拟表)

    • 作用:sql查询语句的执行结果会封装在ResultSet中

    通过上述代码 操作数据库 显然是非常繁琐的,所以在项目开发中很少使用,通常会使用Mybatis这类的高级技术来操作数据库

    数据库连接池

    数据库连接池是个容器,负责分配、管理数据库连接(Connection)

    • 程序在启动时,会在数据库连接池(容器)中,创建一定数量的Connection对象

    允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个

    • 客户端在执行SQL时,先从连接池中获取一个Connection对象,然后在执行SQL语句,SQL语句执行完之后,释放Connection时就会把Connection对象归还给连接池(Connection对象可以复用)

    释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏

    • 客户端获取到Connection对象了,但是Connection对象并没有去访问数据库(处于空闲),数据库连接池发现Connection对象的空闲时间 > 连接池中预设的最大空闲时间,此时数据库连接池就会自动释放掉这个连接对象

    数据库连接池的好处:

    1. 资源重用

    2. 提升系统响应速度

    3. 避免数据库连接遗漏

    现在使用更多的数据库连接池是:Hikari(追光者) [默认的连接池] 、Druid (德鲁伊)

     如果想把默认的数据库连接池切换为Druid数据库连接池,只需要完成以下两步操作即可:

    1. 在pom.xml文件中引入依赖

    1. <dependency>
    2. <!-- Druid连接池依赖 -->
    3. <groupId>com.alibaba</groupId>
    4. <artifactId>druid-spring-boot-starter</artifactId>
    5. <version>1.2.8</version>
    6. </dependency>
    1. 在application.properties中引入数据库连接配置

      1. 方式1
      2. spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver
      3. spring.datasource.druid.url=jdbc:mysql://localhost:3306/mybatis
      4. spring.datasource.druid.username=root
      5. spring.datasource.druid.password=1234
      6. 方式2
      7. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
      8. spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
      9. spring.datasource.username=root
      10. spring.datasource.password=1234

  • 相关阅读:
    大流量、业务效率?从一个榜单开始
    NDSS 2022 EMS: History-Driven Mutation for Coverage-based Fuzzing
    用Python中的马尔科夫链模拟文本
    a-select 下拉列表正常展示
    芯片SoC设计你了解吗?
    一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么?
    【测试沉思录】8. 测试计划应该怎么做?
    智能运维应用之道,告别企业数字化转型危机
    React的jsx的用法
    【[USACO12MAR]Cows in a Skyscraper G】【状压DP && DFS】
  • 原文地址:https://blog.csdn.net/m0_71386740/article/details/138003252