【MyBatis】什么是MyBatis?

文章介绍了MyBatis作为优秀持久层框架的作用,如何简化JDBC操作,包括通过注解执行SQL和使用XML映射文件配置SQL语句。同时,提到了SQL注入问题和动态SQL的使用,如if,foreach和sql标签,以及MyBatis的文件设置总结。
摘要由CSDN通过智能技术生成

MyBatis 是一款优秀的持久层框架,用于简化JDBC的开发。
说人话就是连接数据库并执行SQL的框架。
在这里插入图片描述

0 JDBC简介及流程

【这一节完全可以跳过,理解它是一个连接数据库 & 执行sql的jar包就好,因为后面基本在用MyBatis,基本上不咋直接使JDBC】

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

  • 官方定义的一套操作所有关系型数据库的规则,即接口
  • 各个数据库厂商实现这套接口,提供数据库驱动jar包
  • 我们可以使用这套JDBC接口编程,真正执行的代码是驱动jar包的实现类。

使用的步骤:首先导入驱动jar包。

我的MySQL驱动jar包:F:\MySQL\Program Files (x86)\MySQL\Connector J 8.0\mysql-connector-j-8.0.32.jar

将驱动jar包放入项目下的lib文件夹,并设置add as library。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZFN9MBLK-1686806551629)(【MyBatis】什么是MyBatis?/image-20230615131749568.png)]

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

// 1 注册驱动
// sql 5之后可以不写这一条
Class.ForName("com.mysql.cj.jdbc.Driver");

// 2 连接数据库
url = "jdbc:mysql://127.0.0.1:3306/askcourse";
Connection conn = DriverManager.getConnection(url, username, password);

// 3 定义SQL语句
sql = "";

// 4 获取执行SQL的对象
Statement stmt = conn.createStatement();

// 5 执行SQL
stmt.executeUpdate(sql);

// 6 处理返回结果
// 7 释放资源
stmt.close();
conn.close();

0.1 DriverManager / Connection

1、注册驱动

Class.ForName("com.mysql.cj.jdbc.Driver");

Driver类源码中,这句话对应着:

DriverManager.registerDriver(new Driver())

2、从DriverManger类得到数据库连接。

Connection conn = DriverManger.getConnection('jdbc:mysql://127.0.0.1:3306/数据库名', 用户名, 密码)

0.2 ResultSet

结果集对象,封装了查询语句的结果。

ResultSet res = stmt.executeQuery(sql);

获取查询结果:

boolean next(): 将光标从当前位置移动一行,判断该行是否为有效行
xxx getXxx(): 获取数据

0.3 PreparedStatement

1 SQL注入

SQL注入例子:无论何时,这样拼起来都是true

String name ="hfkjsfhskj";
String pwd = " or '1' ='1"
String sql = "select * from tb_user where username = " + name + " and password = " + pwd;
System.out.printIn(sql);
select * from tb_user where username = 'hfkjsfhskj' and password = '' or '1' = '1'
2 流程

1、获取Connection。

String url = "jdbc:mysql://127.0.0.1:3306/askcourse?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT";
String user = "root";
String password = "********";
Connection conn = DriverManager.getConnection(url, user, password);

2、预编译SQL并填入参数。

String DNO = "C10";
String sql = "SELECT * FROM employee WHERE DNO = ?";

PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, DNO);

3、执行SQL语句。

ResultSet rs = pstmt.executeQuery();

while (rs.next()) {
    System.out.println(rs.getString("DNO"));
}

4、关掉所有的东西。

rs.close();
pstmt.close();
conn.close();

1 MyBatis通过注解执行SQL语句

1.1 MyBatis入门:select

加入Maven依赖,配置连接信息,创建相应实体,创建Mapper及查询方法,添加相应注解。

1、小tips:连接数据库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qx8W8eXS-1686806551629)(【MyBatis】什么是MyBatis?/image-20230614221722305.png)]

2、在pom.xml中加入maven依赖,前者为mybatis的bootstarter,后者为mysql的驱动连接包。

		<dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>

3、在Springboot项目中的application.properties中配置Mybatis数据库连接信息。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KY3J7aga-1686806551630)(【MyBatis】什么是MyBatis?/image-20230614222934825.png)]

3、创建一个实体类User,用于和数据库中的表属性相关联

4、创建UserMapper,一开始的报错Missing method body, or declare abstract是因为,这实际上是个Interface,误写为了Class,改一下就好。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JdvLpRTY-1686806551630)(【MyBatis】什么是MyBatis?/image-20230614225315951.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wHY5P6iH-1686806551630)(【MyBatis】什么是MyBatis?/image-20230614230602501.png)]

5、在test文件夹中的HelloworldApplicationTests应用中,实例化一个UserMapper,并新建testListUser测试。

@SpringBootTest
class HelloworldApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    void testListUser() {
        List<User> userList = userMapper.list();
        userList.stream().forEach(System.out::println);
    }

}

Lombok

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5dGaMtqr-1686806551631)(【MyBatis】什么是MyBatis?/image-20230614232536349.png)]

maven依赖:

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

1.2 依葫芦画瓢:删除

1、新建一个FinishProblemMapper,用于对finishProblem表进行操作。@Mapper注解和@Delete注解。使用#{param}在SQL语句中写入参数。根据主键删除元素

package com.example.helloworld.mapper;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface FinishProblemMapper {

    /**
     * 根据wid与problemId删除指定的做题记录
     * @param wid
     * @param problemId
     */
    @Delete("delete from finished where wid = #{wid} and problemId = #{problemId}")
    public void deleteById(Integer wid, Integer problemId);
}

2、在配置文件中设置mybatis日志

# the log of mybatis
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

3、在test中新建Test

@SpringBootTest
class HelloworldApplicationTests {

    @Autowired
    private FinishProblemMapper finishProblemMapper;


    @Test
    void testDeleteFinishProblem() {
        finishProblemMapper.deleteById(72, 21);
    }

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RWBdKGED-1686806551631)(【MyBatis】什么是MyBatis?/image-20230614234515523.png)]

1.3 插入

传入的参数可以是一个实体。

@Options注解会自动将生成的主键值,赋值给problem的problemId属性。(自动生成主键值

@Mapper
public interface ProblemMapper {

    /**
     * 向Problem表中插入一行problem数据
     * @param problem
     */
    @Insert("insert into problem(problemId, name, url, day) VALUE (#{problemId}, #{name}, #{url}, #{day})")
    public void insert(Problem problem);
}

测试:

    void testProblemInsert() {
        problemMapper.insert(new Problem(202, "快乐数", "https://leetcode.cn/problems/happy-number/", 6));
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bVVYoWOX-1686806551631)(【MyBatis】什么是MyBatis?/image-20230615000054676.png)]

可以设置主键自增,但要先在数据库中进行相应设置。

@Options(keyProperty = "wid", useGeneratedKeys = true)

1.4 更新

类似地,传入的参数可以是一个实体。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZyCSgk6z-1686806551631)(【MyBatis】什么是MyBatis?/image-20230615003445036.png)]

2 通过XML映射文件配置SQL语句

核心:通过xml文件的配置,确定项目中某个Mapper的某个方法对应的SQL语句。

动机:使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java注解不仅力不从心,还会让本就复杂的SQL语句显得更加混乱不堪。选择何种方式来配置映射,以及是否要统一映射语句的形式,完全取决于你和你的团队。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wXajNPB0-1686806551632)(【MyBatis】什么是MyBatis?/image-20230615114025986.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SJRXMuXQ-1686806551632)(【MyBatis】什么是MyBatis?/image-20230615113702009.png)]

当调用ProblemMapper中的selectByDay方法时,Mybatis框架首先会找到相应的xml配置文件,然后找到xml配置文件中的对应方法,并执行对应的SQL语句。

<?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">

<mapper namespace="com.example.helloworld.mapper.ProblemMapper">

    <select id="selectByDay" resultType="com.example.helloworld.model.Problem">
        select * from problem where day = #{day} order by problemId
    </select>

</mapper>

执行test:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2OkkUP4h-1686806551632)(【MyBatis】什么是MyBatis?/image-20230615113803764.png)]

小插件

MyBatisX:安装后点击Mapper中的方法就可以自动定位到xml文件中的SQL语句位置。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D12ks412-1686806551633)(【MyBatis】什么是MyBatis?/image-20230615115123794.png)]

3 动态SQL

if

随着用户的输入或者外部条件的变化而变化的SQL语句。

情景1:希望查询参数为空时select *,不为空时按条件查询,使用<where><if>

情景2:更新时仅更新部分属性,使用<set><if>

<where>可以自动地生成WHERE语句,当语句中没有内容时不会显示,并且可以自动地去掉多余的and或者or。

<set>可以自动地生成set语句,当语句中没有内容时不会显示,并且可以自动地去掉多余的逗号。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wJ6h67NG-1686806551633)(【MyBatis】什么是MyBatis?/image-20230615122509724.png)]

foreach

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mBt4eoFo-1686806551633)(【MyBatis】什么是MyBatis?/image-20230615130451173.png)]

<!-- 批量删除做题记录 -->
    <delete id="deleteByIds">
        delete from finished where wid in
        <!--集合名,元素名,分隔符,开始拼接符号,结束拼接符号-->
        <foreach collection="idList" item="wid" separator="," open="(" close=")">
            #{wid}
        </foreach>
    </delete>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HX7Wu55v-1686806551633)(【MyBatis】什么是MyBatis?/image-20230615130322888.png)]

sql

实现重复sql代码的复用。

如下,通过<sql><include>,实现了commonSelect的复用。

<?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">

<mapper namespace="com.example.helloworld.mapper.ProblemMapper">

    <sql id="commonSelect">
        select problemId, name, url, day from problem
    </sql>

    <select id="selectByDay" resultType="com.example.helloworld.model.Problem">
        <include refid="commonSelect"/> 
        where day = #{day} order by problemId
    </select>

    <select id="list" resultType="com.example.helloworld.model.Problem">
        <include refid="commonSelect"/>
        <where>
            <if test="problemId != null"> problemId = #{problemId}</if>
            <if test="name != null"> and name = #{name}</if>
            <if test="day != null"> and day = #{day} </if>
        </where>
    </select>

</mapper>

4 文件设置总结

application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/problem_tiktok
spring.datasource.username=root
spring.datasource.password=********

# the log of mybatis
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

pom.xml

	<dependencies>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值