《JavaEE进阶》----17.<Mybatis基本操作【注解XML】>

news2024/11/19 17:27:58

本篇博客详细讲解了:编写SQL语句

1.使用注释

2.使用XML

3.多表查询

前言:

Mybatis规范中方法名不能重复,即便参数不同。因为每一个方法名都是有一个唯一的ID标识的。因此不能重复。

我们会将数据库相关的接口放在Mapper包下面。

对,注意我们实现访问数据库的Mapper包下面创建的是接口。

只需要进行方法的声明。

而方法上面的注解/SQL语句才是方法的实现。

@Mapper
public interface UserInfoMapper {
    /**
     * 单纯返回数据列表
     * @return
     */
    @Select("select * from userinfo")  //通过注解的方式 进行 方法的实现 *代表Mybatis所有字段名称
    List<UserInfo> queryUserList(); //方法的声明
@Select("select * from userinfo")  
//通过注解的方式 进行方法的实现 *代表Mybatis所有字段名称
List<UserInfo> queryUserList(); 
//方法的声明

第三步:编写SQL语句

一、通过注解编写SQL语句

1.1查

项目,依赖,数据库,实体类等准备好之后,我们首先建包Mapper(代表操作数据库)(持久层)(因为我们用到Mapper注解)也可以放在dao下面。

新建一个UserInfoMapper类,将它定义成一个接口,我们不做它的实现,这个方法用于返回数据列表。新建一个

List<UserInfo> queryUserList方法来访问这个数据库。 

在类上添加@Mapper注解:用来标识它是操作数据库的。表示是MyBatis中的Mapper接口

在方法上添加@select注解:用来标识SQL语句,代表是select查询。对应方法的具体实现

在查的时候我们发现Java属性中下面蓝框字段为null。

由于Java属性和Mybatis字段不一样,因此不会赋值给Java属性。

最好的办法就是上文我们讲到的配置驼峰自动转换

注:ibatis就是mybatis

①单纯打印数据列表 (如上图就是)

SQL语句1   返回数据列表: 

select * From 表名

示例:

@Select("select * from userinfo")  
//通过注解的方式进行方法的实现 
List<UserInfo> queryUserList(); //方法的声明

使用@select(“select * From userinfo”)这样的方式来写SQL语句

*代表Mybatis所有字段名称。

此时我们就完成了数据库的查询。我们可以通过测试来试试,我们是否完成了数据库的查询。

如上图操作。

② 传递一个参数查询数据列表

SQL语句2   传递一个参数

select * From 表名 where 字段 = 参数;

示例:

select * From userinfo where id = #{userId}
@Select(“select * From userinfo where id = #{userId}”)

注:

当参数只有一个的时候,参数名称无所谓,改成别的也可以拿到值。 

③ 传递两个参数查询数据列表

SQL语句3   传递两个参数

select * From 表名 where 字段 = 参数 and 字段 = 参数;

示例:

@Select(“select * from userinfo where id = #{param1} and delete_flag = #{param2}”)

 我们发现如果按照下面这样写的话。就会报错。因为我使用的是aliyun引入的Mybatis框架。

因此当传递两个参数时,只能使用param1和param2。或者arg1和arg0。作为形参。

 1.若是通过aliyun引入的springframework依赖,那么不会帮我们生成可用的我们定义的参数。因此就会报错。可以用param1和param2。或者arg1和arg0

2.官方的依赖就可以,我们也可以手动修改依赖。也就能实现,自已定义参数名称了。

3.我们也可以进行参数的重命名,这样也可以自定义参数名称。也可以编译通过。

下一条就会讲到了


这样就不会报错,我们使用了param1和param2作为了形参。

④参数重命名@param注解

在方法传参列表的参数前使用@Param注解,我们可以通过参数命名来定义我们想要使用的参数名称。

参数绑定
1.默认是注解的参数名称,使用param1和param2等也可以
2.如果使用@param注解进行重命名,那么注解中的参数必须用重命名后的参数

1.2增

SQL语句4 增添数据表信息

insert into 表名(字段1,字段2,...)values(#{参数1},#{参数2},...)

示例:

intert into userinfo(username,password,age,gender,phone) values(#{username},#{password},#{age},#{gender},#{phone})
@insert("intert into userinfo(username,password,age,gender,phone) values(#{username},#{password},#{age},#{gender},#{phone})")

注:value前面的 username 是数据库字段,value后面的#{username} 是Java属性

使用对象来传参 

通过对象进传递参数
1.没有@Param重命名,那么 Java属性 直接使用属性名

注:

添加的数据在数据库中 id 这个字段是自动生成的。因此无需添加。当然还有时间字段也是自动生成。

@Insert("insert into userinfo(username,password,age,gender,phone)" +
        " values(#{username},#{password},#{age},#{gender},#{phone})")
Integer insert (UserInfo userInfo);

 

测试后我们发现完成添加操作。 

返回值默认是影响的条数。 

 2.使用@Param重命名,那么 Java属性 使用 对象.属性名 来获取参数

​@Options(useGeneratedKeys = true,keyProperty = "id")
//将自动生成的id的数给id这个属性
//此操作相当于setId 来给id赋值, 这样就可以getId,数据库那边不用传参id而是自动生成,而这边自动生成了这个数,但是没有指定给哪个属性。
@Insert("insert into userinfo(username,password,age,gender,phone)" +
" values(#{Info.username},#{Info.password},#{Info.age},#{Info.gender},#{Info.phone})")
Integer insertByParam (@Param("Info") UserInfo userInfo);

​

我们发现如果单纯通过注解重命名那么程序就会报错。会发生绑定异常,如何解决这个问题呢?

我们可以当做@Param(“新参数名”)注解重命名后,新名称的参数我们把它当做一个对象。这样在values()中。我们再绑定属性就需要用新参数名.属性来完成操作了。

@Insert("insert into userinfo(username,password,age,gender,phone)" +
" values(#{Info.username},#{Info.password},#{Info.age},#{Info.gender},#{Info.phone})")

通常我们还想获得数据库中生成的 id 字段。我们若想获得到这个 id 这个属性。就需要我们通过这个注解

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

//此操作相当于将数据库自动生成的 id 的值给id这个属性。相当于我们新建了id(java)属性。
//此操作相当于setId 来给id赋值, 这样就可以getId。

1.3删

SQL语句4:通过id删除

delete from 表名 where id = #{id}

示例:

@delete("delete from userinfo where id = #{id}")

Mapper

Test 

删除成功! 

1.4 改

1.通过传参的方式

SQL语句5:通过id更改数据库某字段值

update 表名 set 字段1 = #{参数1},字段2 = #{参数2},...... where id = #{id参数}

示例:

@Update("update userinfo set password = #{password} where id = #{id} ")

password = #{password}
password:数据库字段

#{password}: Java属性,严格来讲是Mybatis的参数名

​​    @Test
    void update() {
        userInfoMapper.update("nihao",6);
    }

成功修改 。

2.通过传递对象的方式

 

注:

若我们忘了写更新字段值的id,也就是若5已经被删掉了或者本就不存在。IDEA也不会报错,只是影响条数为0。因此没有对数据库进行修改。

二、通过XML方式编写SQL语句

注解和 xml 实现是可以共存的,同一个方法,实现方式选哪个都行。

xml的方式和注解方式的操作基本上是一样的。

操作步骤

1.引入依赖 : 同上

2.配置数据库连接: 同上

3.配置Mapper路径

mybatis:
  mapper-locations: classpath:mapper/**Mapper.xml 
# 配置mybatis xml的⽂件路径,在resources/mapper创建所有表的xml⽂件
# classpath对应resources这个目录,接下来说明在mapper这个文件夹下面,以Mapper.xml结束的都可以被加载

4.声明接口

注意加上Mapper注解。

5.使用xml来实现

数据持久成的实现,MyBatis 的固定 xml 格式:我们要实现的代码就在标签<mapper>中。

创建UserInfoXMLMapper.xml, 路径参考yml中的配置

<?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.demo.mapper.UserInfoMapper">
 
</mapper>

放在resource/mapper目录下面

下图是一些注意事项:

启动失败常见原因:

1.namespace写错了

2.方法名写错了

3.配置错了

2.1增

1.首先声明insert方法,我们使用传递对象的方式来新增数据。

2.在xml文件中,写SQL语句。我们使用传递对象的方式来新增数据。

因此上方我们不仅要设置id 值为对应方法名 以及 返回类型resultType的值为UserInfo(要写全)

 3.测试

通过xml方式拿到自增id

2.2删 

和增一样的三个步骤

1.声明方法

2.在xml文件中写sql语句 

3.Test测试 

2.3改

1.声明方法

2.在xml中写sql语句 

3.Test测试 

2.4查 

查的时候,在xml文件中,有一个resultType它进行了一个映射,把我们的mysql字段映射成java属性。一样的名字会映射,不一样的我们可以在下面的补充看到如何映射。

1.声明方法

2.写SQL语句 

 3.Test测试

 对通过xml+SQL语句查的补充:驼峰转换

1.改别名,和注解是类似的.

2.在xml文件中用resultMap标签进行映射

没写的自动映射,写了的按照我们定义的进行映射,id其实也可以不用写

通过resultMap进行时候用 

3.配置文件自动转换 

同上

三、多表查询

多表查询特点

慢SQL。

业务中使用多表查询比较少,是因为多表查询sql太长了导致性能不好。会造成慢SQL。:原因是

  • 多表查询,我们写一个SQL来查询,那么我们写的就是一个长SQL,这个长SQL是无法被优化的,只能统一交给数据库。可能进行多个表组装。因此大SQL一定会很慢。 影响到整个MySQL数据库集群。它们通过库隔离,但还是一个集群。整个数据库可能都阻塞了。
  • 而单表查询,相当于我们把大SQL拆成了多个小SQL,多个小SQL都是单独的,可以优化,比如多线程的方式,可以并行去查。也可以通过加机器的方式。分配到多个机器上。

建议

  • 如果业务对性能要求不高,那么使用多表查询比使用Java实现更加合适。(例如公司的内部系统,给员工用的)
  • 如果业务对性能要求高,那么使用Java实现更加合适。
  • 尽可能避免多表查询。因为每一个大SQL执行起来很慢,并且还可能影响到其他数据库,影响其他项目。而多个小SQL执行起来比较快。且影响小。

再创建一个表

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);

3.2 第一步:首先进行多表关联(sql语句如下)

3.2.1 SQL语句6(全部查询)

我们在数据库mybatis_test的查询控制台执行那么语句

select * from articleinfo ta
LEFT JOIN userinfo tb on ta.uid = tb.id
where ta.id = 1

解释:

ta:对表articleinfo进行重命名为ta(table a)

LEFT JOIN:左连接,也就是关联的意思

tb: 对表userinfo进行重命名为tb(table b)

on:使用on进行关联,表a的uid字段和表b的id字段

where:查询表a的id

执行后的结果为:

也可以指定查询(SQL语句如下)

3.2.2 SQL语句7(指定查询)

select ta.*,tb.username,tb.password,tb.age
from articleinfo ta
LEFT JOIN userinfo tb on ta.uid = tb.id

我们看到查询到了我们想要的数据。这就是进行多表同时查询。如何用Mybatis来实现这个功能呢。

3.3示例

1.多个表

如上已经添加

2..实体类

package com.qiyangyang.mybatisdemo.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;

}

3. Mapper包

4. Test包

运行结果(成功查询多表) 

四、通过URL来访问数据库

如果我们不想通过测试用例来访问,通过浏览器路径来访问数据库,那么我们首先一定要有Controller来写路由的映射,为了访问数据库相关内容,我们可以直接注入UserInofMapper。但是不符合我们企业开发的规范,因此我们为了规范像企业那样:

分三层架构表现层,业务层,持久层。

因此我们用Controller来调用Service。用Service来调用dao(也就是我们这里的UserInfoMapper)。

建包Controller,Service,分别在其中建类UserController,UserService。

在类UserController中创建public List<UserInfo> queryAllUser() 方法。

并在类上使用@RestController和@RequestMapping注解。在方法上使用RequestMapping注解

4.1UserController 

4.2UserService

我们用Service来调用Dao(也就是数据访问层)。 

4.3UserMapper

ok我们成功的在浏览器访问出来了。 

总结:

1.配置数据库

2.写Mapper

①加注解@Mapper

②方法声明+方法实现

获取参数:#{参数名称}

当只有一个参数时,参数名称叫什么都可以。

当有多个参数就需要与字段对应(使用默认的也可以,不过一般不用),重命名的话与重命名的名字对应。....................

注:

1.访问数据库的方法不能像java那样方法名称相同,参数不同而构成方法的重构。这是会报错的。这不符合Mybatis规范。方法名不可以重复(在xml文件中我们看到每一个方法都是会有一个id标识的因此不能重复)

2.若是通过aliyun引入的springframework依赖,那么不会帮我们生成可用的我们定义的参数。可以用param1和param2。 官方的依赖就可以,我们也可以手动修改依赖。也就能实现,自已定义参数名称了。将aliyun依赖换成官方的依赖。

aliyun的springframework依赖(传参不能自定义参数)

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

官方springframework依赖 (传参可以自定义参数)

<parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>2.7.17</version>

        <relativePath/>

</parent>

三层架构简单回顾

三层架构就是为了符合“高内聚,低耦合”思想,把各个功能模块划分为

  • 表示层(UI)、
  • 业务逻辑层(BLL)和
  • 数据访问层(DAL)

三层架构

各层之间采用接口相互访问,并通过对象模型的实体类(Model)作为数据传递的载体,不同的对象模型的实体类一般对应于数据库的不同表,实体类的属性与数据库表的字段名一致。 

三层架构区分层次的目的是为了 “高内聚,低耦合”。开发人员分工更明确,将精力更专注于应用系统核心业务逻辑的分析、设计和开发,加快项目的进度,提高了开发效率,有利于项目的更新和维护工作。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Latex输入数学期望E及花体符号方法

一、数学期望 E \mathbb{E} E 使用Latex写论文时&#xff0c;我们希望输入如下图所示的数学期望&#xff1a; 方法如下&#xff1a; 首先需要导入\usepackage{amssymb}包&#xff0c;然后正文使用描述为\mathbb{E} 二、花体 B \mathcal{B} B 此外&#xff0c;当我们希望…

外贸获客:主动开发有用吗?

今天主要和大家聊聊&#xff0c;做外贸几个常用的获客渠道。 开发客户的渠道大体上分两种&#xff1a;1、主动开发&#xff1b;2、被动询盘 我们一一进行解析。1、社交媒体开发 即利用社交媒体&#xff0c;如Youtube、LinkedIn、Instagram、TikTok、Facebook等平台进行客户开发…

30道软件测试基础面试题!(含答案)

1、你的测试职业发展是什么&#xff1f; 测试经验越多&#xff0c;测试能力越高。所以我的职业发展是需要时间积累的&#xff0c;一步步向着高级测试工程师奔去。而且我也有初步的职业规划&#xff0c;前 3 年积累测试经验&#xff0c;按如何做好测试工程师的要点去要求自己&a…

JS Reflect 对象 — 深度解析

JS Reflect 对象 — 深度解析 在JavaScript的广阔天地里&#xff0c;Reflect对象如同一面明镜&#xff0c;映射出底层语言操作的精髓。作为前端开发者&#xff0c;掌握Reflect对象及其相关API&#xff0c;无疑能够提升我们的编程技艺&#xff0c;让代码更加简洁、高效。接下来&…

AV1 Bitstream Decoding Process Specification--[1]:术语和定义

原文地址&#xff1a;https://aomediacodec.github.io/av1-spec/av1-spec.pdf没有梯子的下载地址&#xff1a;AV1 Bitstream & Decoding Process Specification摘要&#xff1a;这份文档定义了开放媒体联盟&#xff08;Alliance for Open Media&#xff09;AV1视频编解码器…

浅谈C++入门(1)

​ &#x1f339;个人主页&#x1f339;&#xff1a;喜欢草莓熊的bear &#x1f339;专栏&#x1f339;&#xff1a;C入门 目录 前言 一、C的第一个程序 二、 命名空间 2.1 namespace的价值 2.2 namesapce的定义&#xff08;这里一些东西以记住加理解为主&#xff09; 2.…

国产服务器CPU发展分析

CPU行业概览&#xff1a;信创带动服务器CPU国产化 目前CPU行业由两大生态体系主导&#xff1a;一是基于X86指令系统和Windows操作系统的Wintel体系&#xff0c;主要用于服务器与电脑等&#xff1b;二是基于ARM指令系统和Android操作系统的AA体系&#xff0c;主要用于移动设备…

数据结构加餐:三路划分、自省排序、文件归并排序

数据结构加餐1 1.快排之三路划分2.快排之自省排序3.文件归并排序3.1外排序3.2归并排序的实现3.2.1归并排序思想3.2.2文件归并排序代码实现 1.快排之三路划分 在之前完成的快排仍然存在这一些问题&#xff0c;当重复数据较多时&#xff0c;快速排序选择的基值也会较不恰当&#…

SaaS化多租户实现的两种方法

SaaS化多租户实现的两种方法 SaaS系统的定义 SaaS&#xff0c;全称为Software-as-a-Service&#xff08;软件即服务&#xff09;&#xff0c;是一种基于云计算的软件交付模式。而SaaS系统&#xff0c;即是通过这种模式提供给用户的软件系统。即多租户系统&#xff0c;每个租户…

MySQL 日志篇:Redo 文件和自适应检查点

MySQL 的 InnoDB 存储引擎使用 Redo Log 记录事务对数据的更改&#xff0c;以便在系统崩溃恢复时能够重做这些更改&#xff0c;从而保证事务的持久性。对于产生的 Redo Log&#xff0c;InnoDB 存储引擎首先将其写入内存中的 Log Buffer&#xff0c;随后再将 Log Buffer 中的 Re…

力扣337-打家劫舍 III(Java详细题解)

题目链接&#xff1a;337. 打家劫舍 III - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 本体是打家劫舍的一个变形题&#xff0c;希望大家能先做198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09;&#xff0c;并看一下我上题的讲解力扣198-打家劫舍&…

【刷题】Day 3--错误的集合

hello&#xff01;又见面啦~~~ 一道习题&#xff0c;要长脑子了...... 【. - 力扣&#xff08;LeetCode&#xff09;】 【思路】 /*** Note: The returned array must be malloced, assume caller calls free().*/void Bubble_sort(int arr[], int size) {int temp;for (int i…

多速率信号处理-CIC滤波器

基本原理 级联积分梳状滤波器&#xff08;Cascade Intergrator Comb&#xff09;是多速率信号处理中一种十分高效的数字滤波器。CIC滤波器具有低通滤波器的特性&#xff0c;同时具有以下优势&#xff1a; 滤波器系数全为1&#xff0c;设计时不需要存储滤波器系数&#xff0c;…

拖放WORD文件朗读全文

把WORD拖放到tkinter的窗口&#xff0c;就可以朗读整改word文件的内容。 代码&#xff1a; # -*- coding: utf-8 -*- """ Created on Tue Sep 10 17:09:35 2024author: YBK """ import pyttsx3 import comtypes.client import os import tkint…

按包边(边框)尺寸分类异形创意圆形(饼/盘)LED显示屏有哪些种类

在LED显示屏技术日新月异的今天&#xff0c;异形创意圆形&#xff08;饼/盘&#xff09;LED显示屏凭借其独特的形态设计与广泛的应用场景&#xff0c;成为了商业展示、舞台表演、艺术装置以及户外广告等领域的宠儿。其中&#xff0c;按包边&#xff08;边框&#xff09;尺寸的不…

holynix靶机详解

靶机配置 加一个网络适配器&#xff08;网卡&#xff09; 修改MAC地址 00:0C:29:BC:05:DE 原来的网卡设置为桥接&#xff0c;随机生成MAC地址 重启靶机即可扫到靶机IP 主机探测与端口扫描 arp-scan -l 发现开放80端口 nmap -sV -A -T4 192.168.229.153 访问网站 http://1…

OpenAI O1:人工智能推理能力的新里程碑

引言 北京时间9月13日凌晨&#xff0c;OpenAI在没有任何预告的情况下&#xff0c;正式发布了其首款具有推理能力的模型——OpenAI O1。这一模型的发布&#xff0c;不仅标志着人工智能能力的新水平&#xff0c;也预示着AI技术发展的新范式。本文将详细解析OpenAI O1模型的技术特…

【计网】数据链路层:概述之位置|地位|链路|数据链路|帧

✨ Blog’s 主页: 白乐天_ξ( ✿&#xff1e;◡❛) &#x1f308; 个人Motto&#xff1a;他强任他强&#xff0c;清风拂山岗&#xff01; &#x1f4ab; 欢迎来到我的学习笔记&#xff01; ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ 1. 在OSI体系结构中的位置 1. 位置&#xff1a;数…

每日一练:K个一组翻转链表

25. K 个一组翻转链表 - 力扣&#xff08;LeetCode&#xff09; 一、题目要求 给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#x…

时间复杂度计算 递归

我们先拿出 2021 csp-s 程序题中一道看着就头大的程序题&#xff0c;要求分析 solve1 的复杂度。 设 T(n) ⁡ \operatorname{T(n)} T(n) 表示数组长度为 n n n 时的复杂度&#xff08;即 m − h 1 n m-h1n m−h1n&#xff09;。 T ( 1 ) 1 T(1)1 T(1)1&#xff0c;根据…