MyBatis 入门使用(二)

MyBatis的开发有两种方式:注解和XML,上一期我们学习了使用注解的方式,这期我们学习XML的方式。

使用注解主要是用来完成一些简单的增删改查功能,如果需要实现复杂的SQL功能,建议使用XML来配置映射语句。

1. 使用步骤

1.1 配置连接字符串和MyBatis

在配置文件中填写以下配置信息:

spring:
  application:
    name: J20240402-MyBatis
#数据库连接配置
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
# 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件
mybatis:
  mapper-locations: classpath:mapper/**Mapper.xml

mapper-locations: classpath:mapper/**Mapper.xml

mapper-locations: 用于指定Mapper XML文件的位置。

classpath:mapper/**Mapper.xml:classpath表示resources文件夹,表示把xm文件夹放在resource文件夹下的mapper文件夹中,并且xml文件必须是Mapper.xml结尾,**表示通配符。

1.2 接口定义

和使用注解相同我们同样需要先定义接口和方法:

package com.example.mybatis.mapper;

import com.example.mybatis.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserInfoXMLMapper {
    Integer insert(UserInfo userInfo);
}

1.3 接口实现

我们需要在1.1中指定的路径中创建一个符合要求的xml文件:

然后在xml文件中实现接口中的方法:

在此之前我们需要先在xml文件中填写固定的xml格式:

<?xml version="1.0" encoding="UTF-8"?> <!--xml版本和编码格式-->

<!--用于指定XML文档类型及其DTD(文档类型定义)的位置-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--指定了该Mapper XML文件所属的命名空间,即com.example.demo.mapper.UserInfoXMLMapper,我们定义的接口的路径-->
<mapper namespace="com.example.mybatis.mapper.UserInfoXMLMapper">

</mapper>

接下来我们只需在mapper标签中实现对应的方法:

<mapper namespace="com.example.mybatis.mapper.UserInfoXMLMapper">
    <insert id="insert">
        insert into userinfo (username, password, age, gender)
        values (#{username}, #{password}, #{age}, #{gender})
    </insert>
</mapper>

SQL语句的构造和使用注解的方式相同

单元测试:

@SpringBootTest
class UserInfoXMLMapperTest {
    @Autowired
    UserInfoXMLMapper userInfoXMLMapper;
    @Test
    void insert() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("liHua");
        userInfo.setPassword("liHua");
        userInfo.setAge(20);
        userInfo.setGender(2);
        System.out.println(userInfoXMLMapper.insert(userInfo));
    }
}

运行代码:

2. 基本操作

前面已经演示了xml如何使用,接下来的增删改查操作我们就简单看一下代码:

@Mapper
public interface UserInfoXMLMapper {
    Integer insert(UserInfo userInfo);

    Integer delete(Integer id);

    Integer update(UserInfo userInfo);

    List<UserInfo> select();
}
<mapper namespace="com.example.mybatis.mapper.UserInfoXMLMapper">
    <insert id="insert">
        insert into userinfo (username, password, age, gender)
        values (#{username}, #{password}, #{age}, #{gender})
    </insert>

    <delete id="delete">
        delete from userinfo where id = #{id}
    </delete>

    <update id="update">
        update userinfo set username = #{username}, password = #{password}, age = #{age}, gender = #{gender} where id = #{id}
    </update>

    <select id="select" resultType="com.example.mybatis.model.UserInfo">
        select * from userinfo
    </select>
</mapper>

由于select的返回类型不唯一,所以需要指定返回类型

@SpringBootTest
class UserInfoXMLMapperTest {
    @Autowired
    UserInfoXMLMapper userInfoXMLMapper;
    @Test
    void insert() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("liHua");
        userInfo.setPassword("liHua");
        userInfo.setAge(20);
        userInfo.setGender(2);
        System.out.println(userInfoXMLMapper.insert(userInfo));
    }

    @Test
    void delete() {
        System.out.println(userInfoXMLMapper.delete(10));
    }

    @Test
    void update() {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(11);
        userInfo.setUsername("Hua");
        userInfo.setPassword("Hua");
        userInfo.setAge(25);
        userInfo.setGender(1);
        System.out.println(userInfoXMLMapper.update(userInfo));
    }

    @Test
    void select() {
        System.out.println(userInfoXMLMapper.select());
    }
}

注意:使用xml的方式查询时依然存在字段名不相同无法赋值的情况,解决方法仍然有三种:

1. 起别名(和使用注解相同)

2.结果映射

3.驼峰自动转换(和使用注解相同)

结果映射:

<mapper namespace="com.example.mybatis.mapper.UserInfoXMLMapper">
    <resultMap id="resultMap" type="com.example.mybatis.model.UserInfo">
        <id column="id" property="id"></id>
        <result column="delete_flag" property="deleteFlag"></result>
        <result column="create_time" property="createTime"></result>
        <result column="update_time" property="updateTime"></result>
    </resultMap>
    <select id="select" resultMap="resultMap">
        select * from userinfo
    </select>
</mapper>

主键映射一般使用 id ,其他使用result

3. 其他查询操作

3.1 多表查询 

数据准备:

我们已经有了一张工作表,我们再来建一张文章表:

-- 创建⽂章表
DROP TABLE IF EXISTS articleinfo;
CREATE TABLE articleinfo (
id INT PRIMARY KEY auto_increment,
title VARCHAR ( 100 ) NOT NULL,
content TEXT NOT NULL,
uid INT NOT NULL,
delete_flag TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
create_time DATETIME DEFAULT now(),
update_time DATETIME DEFAULT now()
) DEFAULT charset 'utf8mb4';
-- 插⼊测试数据
INSERT INTO articleinfo ( title, content, uid ) VALUES ( 'Java', 'Java正⽂', 1
);

准备对应的类:

package com.example.mybatis.model;

import lombok.Data;
import java.util.Date;
    @Data
    public class ArticleInfo {
    private Integer id;
    private String title;
    private String content;
    private Integer uid;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

需求:查询文章信息和对应的作者信息:

创建接口:

package com.example.mybatis.mapper;

import com.example.mybatis.model.ArticleInfo;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface ArticleInfoMapper {
    List<ArticleInfo> getArticleAndUser(Integer id);
}

我们发现,如果我们使用 ArticleInfo 接收结果的话是行不通的,因为查询结果还包含了UserInfo的数据,所以我们可以创建一个新类来接收,或者在ArticleInfo中添加UserInfo中的属性:

package com.example.mybatis.model;

import lombok.Data;
import java.util.Date;
@Data
public class ArticleInfo {
    private Integer id;
    private String title;
    private String content;
    private Integer uid;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
    
    //UserInfo
    private String username;
    private Integer age;
    private Integer gender;
}

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">
<mapper namespace="com.example.mybatis.mapper.ArticleInfoMapper">
    <select id="getArticleAndUser" resultType="com.example.mybatis.model.ArticleInfo">
        select a.* b.username, b.age, b.gender
        from articleinfo a left join userinfo b on a.uid = b.id where a.id = #{id};
    </select>
</mapper>

单元测试:

3.2 #{} 和 ${} 

MyBatis 参数赋值有两种方式,前面我们使用了 #{},接下来我们介绍 ${},以及它们的区别

3.2.1 ${}使用 

${}的使用方式和 #{}相同,都是用来框选参数。

我们分别运行这两个方法:

我们对比发现: 前者的SQL语句是使用的 ?进行占位,这种SQL我们称为预编译SQL,后者则是直接把 参数拼接上去,我们称为即时SQL。如果我们把参数类型换为 String类型会出现一个问题:

我们发现使用 #{}能运行成功,使用${}发生了报错信息,我们观察报错语句中的SQL,发现 SQL中没有给admin加引号,所以导致了错误,现在我们在${}外面加上引号再次运行:

 正常运行。

3.1.2 #{} 和 ${} 的区别

#{}和${}的区别就是预编译SQL和即时SQL的区别

1.性能

当服务器接收到一条SQL之后会发生以下流程:

 大多数情况下,一条SQL语句会被反复执行,只是每次的参数有个别不同,如果每次都要完整的经历上述步骤,那么会大大降低效率,预编译SQL编译一次之后会将编译后的SQL语句缓存起来,后面执行时再次执行到这条语句时不会再次编译,直接把参数替换后直接执行。即时SQL则每次都是一条全新的SQL会完整经历每个步骤。

2. 安全

使用${}有被SQL注入攻击的风险:

用刚才的代码举例:由于${}是拼接的方式来构造SQL,如果输入时输入:' or 1='1,这时我们的SQL语句就变成了:select * from userinfo where username = '' or 1='1'  那么此时会把我们所有的内容都查出来,因为 1 一定等于 1,所以我们能使用 #{}的场景都尽量使用 #{}

3.3 ${} 使用场景

有时候我们可能需要输入 SQL语句的非参数部分来作为参数,此时就不需要加引号也就要用到 ${},例如排序场景:

 

此时我们传入 desc 或者 asc 来决定升序或降序是不能加引号的

3.4 like查询

分别运行两个方法:

 

这里的参数是不能加引号的所以#{}运行失败,不过我们可以使用SQL中的字符串拼接函数:

4. 数据库连接池

SprintBoot使用了数据库连接池技术避免了频繁的创建连接,销毁连接。

数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接(类似于线程池),程序启动时,会在数据库连接池中创建一定数量的Connection对象,当客户请求数据库连接时,会从数据库连接池中获取Connection对象,然后执行SQL,SQL语句执行完,再把Connection归还给连接池。

常见的数据库连接池有:

  • C3P0
  • DBCP
  • Druid
  • Hikari

目前比较流行的是:Hikari,Druid,SpringBoot默认使用的是Hikari

我们如果想更换数据库连接池只需引入相关依赖即可。

5. MySQL 开发企业规范

  1. 表名,字段名使用小写字母或数字,单词之间以下划线分割,尽量避免数字开头或者两个下划线中间只出现数字,数据库字段名的修改代价很大,所以字段名需要慎重考虑。
  2. 表必备三个字段:id(主键),create_time,update_time
  3. 在表查询中,避免使用 * ,标明哪些字段需要查询

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/523349.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

day02 VS Code开发单片机

VS Code开发单片机 1.1 安装 MinGW-w64 1)MinGW-w64介绍 VS Code 用于编辑 C 代码,我们还需要 C 编译器来运行 C 代码,所以安装 VS Code之前我们需要先安装 C 编译器。这里我们使用 MinGW-w64(Minimalist GNU for Windows 64-bit)。 MinGW-w64 是一个用于Windows操作系…

Transformer模型-broadcast广播的简明介绍

broadcast的定义和目的&#xff1a; 广播发生在将较小的张量“拉伸”以具有与较大张量兼容的形状&#xff0c;以便执行操作时。 广播是一种有效执行张量操作而不创建重复数据的方式。 广播的处理过程&#xff1a; 1&#xff0c; 确定最右边的维度是否兼容 每…

2024/4/7 IOday6

1&#xff1a;有一个隧道&#xff0c;全长5公里&#xff0c;有2列火车&#xff0c;全长200米&#xff0c; 火车A时速 100公里每小时 火车B时速 50公里每小时 现在要求模拟火车反复通过隧道的场景(不可能2列火车都在隧道内运行) #include <stdio.h> #include <string.…

Redis 的主从复制、哨兵和cluster集群

目录 一. Redis 主从复制 1. 介绍 2. 作用 3. 流程 4. 搭建 Redis 主从复制 安装redis 修改 master 的Redis配置文件 修改 slave 的Redis配置文件 验证主从效果 二. Redis 哨兵模式 1. 介绍 2. 原理 3. 哨兵模式的作用 4. 工作流程 4.1 故障转移机制 4.2 主节…

tabby 创建ssh远程配置提示:Timed out while waiting for handshake

不知道是不是网络延迟还是虚拟机克隆链接的问题&#xff0c;使用tabby无法正常的ssh远程过去&#xff0c;链接提示信息如下&#xff1a; SSH Connecting to 192.168.36.10SSH ! Agent auth selected, but no running agent is detectedSSH Host key fingerprint:SSH ecd…

Android匿名共享内存(Ashmem)

在Android中我们熟知的IPC方式有Socket、文件、ContentProvider、Binder、共享内存。其中共享内存的效率最高&#xff0c;可以做到0拷贝&#xff0c;在跨进程进行大数据传输&#xff0c;日志收集等场景下非常有用。共享内存是Linux自带的一种IPC机制&#xff0c;Android直接使用…

深入解析War包和Jar包机制

一、概述 代码编写完成后&#xff0c;需要部署到服务器&#xff0c;但部署到服务器对文件格式是有要求&#xff0c;原生的源代码目前是无法支持直接部署到服务器上的。目前有两种主要的文件格式War包和Jar包&#xff0c;通过一定的机制将源代码变成War包或Jar包&#xff0c;就…

42. 接雨水(Java)

目录 题目描述:输入&#xff1a;输出&#xff1a;代码实现&#xff1a; 题目描述: 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 输入&#xff1a; height [0,1,0,2,1,0,1,3,2,1,2,1]输出&#xff1…

WebKit是什么?

WebKit是一个开源的浏览器引擎&#xff0c;它用于呈现网页内容在许多现代浏览器中&#xff0c;包括Safari浏览器、iOS内置浏览器、以及一些其他浏览器如Google Chrome的早期版本。以下是一些关于WebKit的重要信息&#xff1a; 起源和发展&#xff1a;WebKit最初是由苹果公司为其…

上传文件报错e20004 阿里云盘:空间不足 送的空间突然全到期了。免费无法长久 百度网盘扛住了压力,没有跟风。

https://blog.csdn.net/chenhao0568/article/details/137332783?spm1001.2014.3001.5501 免费撑不住了&#xff0c;这样下去干不过老大呀。百度网盘扛住了压力&#xff0c;没有跟风。

计算机网络——34LANs

LANs MAC地址和ARP 32bit IP地址 网络层地址用于使数据到达目标IP子网&#xff1a;前n - 1跳从而到达子网中的目标节点&#xff1a;最后一跳 LAN&#xff08;MAC/物理/以太网&#xff09;地址&#xff1a; 用于使帧从一个网卡传递到与其物理连接的另一个网卡&#xff08;在同…

计算机网络练习-计算机网络概述与性能指标

计算机网络概述 ----------------------------------------------------------------------------------------------------------------------------- 1. 计算机网络最据本的功能的是( )。 1,差错控制 Ⅱ.路由选择 Ⅲ,分布式处理 IV.传输控制 …

人眼对亮度的感知

对比两本书的说法 计算机图形学的算法基础 david f.rogers 如图所示: 然后看数字图像处理_第三版_中_冈萨雷斯的说法&#xff1a; 视觉错觉对于做图像处理没有什么大用。前面两点有用。 第一点。马赫带效应&#xff0c;明暗变化太强的时候&#xff0c;出现马赫带。较明区域是…

蓝桥杯刷题-14-更小的数-区间DP⭐

蓝桥杯2023年第十四届省赛真题-更小的数 //区间DP #include <iostream> #include<bits/stdc.h> #define int long long using namespace std; const int N5e310; int f[N][N]; void solve(){string s;cin>>s;int ans0;for(int len2;len<s.size();len){for…

Sora是什么?Sora怎么使用?Sora最新案例视频以及常见问题答疑

Sora 是什么&#xff1f; 2024年2月16日&#xff0c;OpenAI 在其官网上面正式宣布推出文本生成视频的大模型Sora 这样说吧给你一段话&#xff0c; 让你写一篇800字的论文&#xff0c;你的理解很可能都有偏差&#xff0c;那么作为OpenAi要做文生视频到底有多难&#xff0c;下面…

牛市来临,模块化赛道可能会出现下个以太坊?

市场专家普遍预测&#xff0c;2024年将成为加密货币市场迎来新一轮牛市的关键时刻。研究人员将下一次比特币&#xff08;BTC&#xff09;减半以及2024年现货BTC ETF&#xff08;交易所交易基金&#xff09;的可能性视为推动下一次牛市的潜在因素。这一牛市的可能爆发有望吸引大…

Leetcode 148. 排序链表

心路历程&#xff1a; 这道题通过很简单&#xff0c;但是如果想要用O(1)的空间复杂度O(nlogn)的时间复杂度的话&#xff0c;可能得需要双指针快排的思路。 解法&#xff1a;遍历模拟 # Definition for singly-linked list. # class ListNode: # def __init__(self, val0…

Pillow教程09:图片格式(png,jpg,ico等)批量转换+批量修改图片尺寸

---------------Pillow教程集合--------------- Python项目18&#xff1a;使用Pillow模块&#xff0c;随机生成4位数的图片验证码 Python教程93&#xff1a;初识Pillow模块&#xff08;创建Image对象查看属性图片的保存与缩放&#xff09; Pillow教程02&#xff1a;图片的裁…

PLM系统同步到SAP修改、停用BOM数据

MATNR 1 类型 MATNR CHAR 40 0 0 物料编号 WERKS 1 类型 WERKS_D CHAR 4 0 0 工厂 STLAN 1 类型 STLAN CHAR 1 0 0 物料清单用途 STLAL 1 类型 STLAL CHAR 2 0 0 备选物料清单 AENNR …

2024.4.7作业

//登陆界面 this->setWindowTitle("传奇霸业"); this->setWindowIcon(QIcon("C:\\Users\\l1693\\Desktop\\pictures\\1.png")); this->resize(400,300); this->setFixedSize(400,300); //登录界面修饰 //底图 QLabel *lab5 new QLabel(this);…