MyBatis框架基础到进阶

1、为什么要学习MyBatis

        如果没有MyBatis框架,我们依靠JDBC和连接池已经能够很好的和数据库进行交互了,而学习MyBatis框架最核心的原因是为了减少SQL语句对代码的侵入性。

        因为在过往不管是使用连接池还是JDBC Templete,所有的SQL语句都写在代码中,这导致了

        一、SQL语句与代码的耦合性太高并且写死的SQL语句无法在其他代码中进行复用

        二、我们需要记忆很多操作数据库的方法(例如queryForList、queryForMap……)

2、MyBatis介绍

        一、原是Apache的一个开源项目叫做iBatis,后因为商标冲突与2010年被更改为MyBatis

        二、MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架,它避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的操作。

        三、MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的实体类映射成数据库中的记录

3、SpringBoot整合MyBatis

①引入依赖

这里不需要引入Spring对JDBC的依赖,因为MyBatis会自动引入

<!--mysql数据库驱动依赖-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope>
</dependency>
<!--引入相关mybatis依赖-->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version>
</dependency>

②在yml文件中配置数据源

spring:datasource:url: jdbc:mysql://localhost:3306/empdb?serverTimezone=Asia/Shanghai&characterEncoding=utf8&serverTimeZone=Asia/Shanghaiusername: rootpassword: Qwertuiop123.
一、基于注解使用MyBatis(掌握即可,工作中一般使用XML形式进行数据库编程)

        基于注解方法使用是通过SQL语句和接口方法相绑定,从而达到在调用方法时就可以执行SQL语句

①准备实体类,用于将数据库查询信息封装到实体类中

@Data
public class Teacher {private long id;private String name;private long age;private String title;private long manager;private long salary;private long comm;private String gender;private long subjectId;}

②准备一个持久层接口方法

一般来讲一个接口操作一张表,比如说下面这个接口里定义的方法就是专门用于操作Teacher表

@Mapper
public interface TeacherMapper {@Select("SELECT * FROM teacher")//如果SQL操作后返回的是一条结果,则直接将返回值定义为返回的实体类型//如果SQL操作后返回的是多条结果,则直接将返回值定义为返回的实体类型的集合并定义泛型public List<Teacher> getTeacherAll();//如果SQL绑定的是增删改语句,如果要求返回执行的记录数,则将返回值类型改为int;如果不要求返回则可以改为void@Insert("INSERT INTO teacher VALUES (6666,'光头师傅',22,'宗师',null,100000,50000,'男',0);")public int addTeacher();
}

③准备测试代码

@SpringBootTest
public class TestMyBatisAnno {@Autowiredprivate TeacherMapper teacherMapper;@Testpublic void testSelectAll() {List<Teacher> teacherAll = teacherMapper.getTeacherAll();for (Teacher teacher : teacherAll) {System.out.println(teacher);}}
}

        注意:当数据库表字段由多个单词组成或表字段形式为xxx_xxx时,我们要在yml配置中配置驼峰规则映射,否则该字段的值无法查询到

#开启驼峰规则
mybatis:configuration:map-underscore-to-camel-case: true
二、@MapperScan注解的使用

        随着后续的开发,可能这样的Mapper接口会变得很多,那么可能每个接口都要加@Mapper注解,就会变得很麻烦,所以可以在SpringBoot的主启动类上添加@MapperScan注解,并指定要扫描的mapper包,这样的话,就会自动去获取指定包下的接口了。

        但这样做也会有一个问题,因为我们的持久层的接口一定是要被注入的,当项目没有启动并且在持久层上又没有加mapper注解时,在注入的接口上会有红色波浪线报错提示,大概报错内容是"Spring容器中没有这个bean",所以尽可能在开发过程中还是勤写@mapper注解

三、基于XML文件使用MyBatis

①定义xxxMapper.xml文件,这个文件的命名一般都为表名+mapper,也就是说和持久层的接口名相同

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">//namespace中指定要绑定接口的全路径
<mapper namespace="cn.tedu.mapper.StudentMapper">//id值要和接口中的对应方法名相同
//在查询SQL中,必须指定resultType,它的值和对应接口方法的返回值类型相同<select id="getStudentAll" resultType="cn.tedu.pojo.Student">SELECT id, name, age, gender, job, birth, location_id, team_leader, class_id FROM student</select></mapper>

②指定MyBatis中mapper文件扫描路径(即找到SQL文件的所在位置)

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

③定义测试文件(在这里不做赘述,和使用注解的时候一致)

四、在mapper.xml中占位符的介绍

当我们在SQL查询语句中需要根据参数查询时,我们需要将该参数用 #{参数} 表示,并且在对应的接口方法中传入形参

①当参数为一个时:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="tedu.mapper.StudentMapper"><select id="getStudentById" resultType="tedu.pojo.Student">SELECT *FROM student WHERE id = #{id}</select></mapper>
public interface StudentMapper {//这里的形参值比一定要和SQL中占位符内的参数一样,但是为了代码的可读性,一般都定义为一样的public Student getStudentById(Long id);}

 ②当参数为多个时:SQL中占位符内的参数名必须要和接口方法中的参数名一致

 <select id="getStudentByBirth" resultType="cn.tedu.pojo.Student">SELECT id,name,age,gender,job,birth,location_id,team_leader,class_idFROM studentWHERE birth > #{minbirth}//在配置文件中 < 为特殊符号,所以直接写会报错,因此需要使用替换符AND birth &lt; #{maxbirth}</select>
public interface StudentMapper {public List<Student> getStudentByBirth(String minBirth, String maxBirth);}

        ③当SQL中占位符中传入多个参数正好是属于一个实体类中的属性,则该参数直接命名为对应实体类中的属性即可,例如:

 <insert id="addStudent">INSERT INTO studentvalues (#{id}, #{name}, #{age}, #{gender}, #{job}, #{birth}, #{locationId}, #{teamLeader}, #{classId})</insert>
public interface StudentMapper {public int addStudent(Student student);}
五、ResultMap——手动映射和ResultType——自动映射

        ResultType 在之前我们已经使用实际案例说过了,就是通过SQL语句中的字段名和实体类中的属性名相关联,将访问数据库之后的结果封装到对应Type的实体类中,它是属于自动映射。

        当然,这样的映射方式也有一个弊端,当我们在xml文件的SQL语句中给某些字段取别名时,通过自动映射结果为null,即SQL字段和实体类属性不能完成匹配

 

       

        而resultMap可以手动的将属性和表字段匹配

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.tedu.mapper.TeacherMapper"><select id="getTeacherById" resultMap="teacher">SELECT id idddd,name,age,title,manage,salary sal,comm,gender gen,subject_id sub,FROM TeacherWHERE id = #{id}</select><!--resultMap自定义映射规则type: 自定义映射的实体类,相当于ResultType后面的值id:唯一id,resultMap中的id字段要和上方resultMap中的值相一致建议只要定义resultMap,就将整表的全部列的映射全部写上--><resultMap id="teacher" type="cn.tedu.pojo.Teacher"><!--指定主键列的封装规则id映射主键,底层会有优化column:指定数据库表的哪一列,如果在SQL中定义了别名则需要写别名property:指定实体类的属性--><id column="idddd" property="id"/><!--result:映射普通字段--><result column="name" property="name"/><result column="age" property="age"/><result column="title" property="title"/><result column="manager" property="manager"/><result column="sal" property="salary"/><result column="comm" property="comm"/><result column="gen" property="gender"/><result column="sub" property="subjectId"/></resultMap>
</mapper>

         当然,ResultMap也没有咱们想的这么不智能,它还是可以和自动映射兼容的(即ResultMap也可以实现自动映射),当数据库表字段列和实体类属性列一致时,我们同样可以将它删除,完成自动映射。

        也就是说上方的代码改成如下也没有问题,原因是ResultMap规则中会有一个默认属性autoMapping=true属性,如果改为autoMapping=false则会映射失败。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.tedu.mapper.TeacherMapper"><select id="getTeacherById" resultMap="teacher">SELECT id idddd,name,age,title,manage,salary sal,comm,gender gen,subject_id sub,FROM TeacherWHERE id = #{id}</select><resultMap id="teacher" type="cn.tedu.pojo.Teacher"><id column="idddd" property="id"/><result column="sal" property="salary"/><result column="gen" property="gender"/><result column="sub" property="subjectId"/></resultMap>
</mapper>
六:ResultMap的高级用法:级联操作

        一对一映射

        当我们进行多表联查时,很明显,一张表内会有另一张表的关联信息(例如老师表和科目表,老师表内部一定会有一个字段和科目表产生联系),此时,只在手动映射规则中添加一个实体类显然不能满足要求 ,此时我们可以采取如下操作:

①在其中一张表(以教师表为例)中添加另一张表(以科目表为例)的类属性

        注意:这里因为是一个老师教一个科目,相当于是一个一对一的关系,所以在添加的subject属性直接使用类就可以,但是如果一个老师教多个科目,则相当于是一个一对多的关系,因此添加的subject属性应该是一个集合类 ,例如 "private List<Subject> subject "      

②在mapper.xml文件的SQL语句中做映射关系

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.tedu.mapper.TeacherMapper"><select id="getTeacherById" resultMap="teacher">SELECT *FROM TeacherWHERE id = #{id}</select><select id="getTeacherSubjectById" resultMap="teacher2">SELECT t.id,t.name,t.age,t.title,t.manager,t.salary,t.comm,t.gender,t.subject_id,<!--以下两个字段属于科目表,而字段名和教师表相同,必须取别名-->s.id sid,s.name snameFROM teacher t,subject sWHERE t.subject_id = s.idAND t.id = #{id};</select><!--联合查询: 使用级联属性封装结果集--><resultMap id="teacher2" type="Teacher" ><id column="id" property="id"/><result column="name" property="name"/><result column="age" property="age"/><result column="title" property="title"/><result column="manager" property="manager"/><result column="salary" property="salary"/><result column="comm" property="comm"/><result column="gender" property="gender"/><result column="subject_id" property="subjectId"/><!--通过教师表的subject属性映射到科目表的id和name属性--><result column="sid" property="subject.id"/><result column="sname" property="subject.name"/></resultMap>
</mapper>

        一对多映射 

        ①在其中一张表(以科目表为例)中添加另一张表(以教师表为例)的类属性,因为一个科目有多个老师教,所以定义的老师类应该是一个集合

        ②在mapper.xml文件的SQL语句中做映射关系,这里需要使用collection标签

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.tedu.mapper.SubjectMapper"><select id="getSubjectTeacherByName" resultMap="subject">SELECT s.id,s.name,t.id   tid,t.name tname,t.age,t.title,t.manager,t.salary,t.comm,t.gender,t.subject_idFROM subject sLEFT JOIN teacher t ON s.id = t.subject_idWHERE s.name = #{name};</select><resultMap id="subject" type="Subject"><id column="id" property="id"/><result column="name" property="name"/><!--collection:表示要开始一对多映射property:表示要进行一对多映射的属性名,即下面这些字段要映射到Subject类的那个属性里呢ofType 表示一对多映射的属性的类型,相当于一对一映射关系中的type,表示要映射的实体类的属性--><collection property="teachers" ofType="Teacher"><!--定义集合中的元素的封装规则--><id column="tid" property="id"/><result column="tname" property="name"/><result column="age" property="age"/><result column="title" property="title"/><result column="manager" property="manager"/><result column="salary" property="salary"/><result column="comm" property="comm"/><result column="gender" property="gender"/><result column="subject_id" property="subjectId"/></collection></resultMap>
</mapper>

4、日志配置

        日志的作用是用来追踪和记录我们的程序运行中的信息,我们可以利用日志很快定位问题,追踪分析,

        在以上测试中,虽然最终测试都成功了,但是我们没办法清晰的指导知道哪条查询的结果是对应哪条SQL语句的,使用日志就能够结解决这个问题。

日志级别:

        SpringBoot的日志框架提供了如下几种日志级别(从高到低,日志级别越高,反映在控制台所打印的内容就越少,比如ERROR级别他就只打印程序的错误信息;WARN级别可能同时会打印警告和错误信息):

  • ERROR:错误级别,指出发生错误事件,需要立即处理;

  • WARN:警告级别,表明可能发生错误的情况,需要注意和防止;

  • INFO:信息级别,描述应用程序的正常运行信息,但不会打印太多的信息;(SpringBoot默认级别)

  • DEBUG:调试级别,用于调试应用程序,打印详细的调试信息;

  • TRACE:跟踪级别,记录应用程序中每个步骤的详细信息。

在配置文件中设置日志级别:

 注意:一定要设置扫描主启动类所在的包的内容,这里的cn.tedu就是主启动类所在的包

#日志设置
logging:level:cn:tedu: debug

—————————————————————

路漫漫其修远兮,吾将上下而求索~
到此关于MyBatis基础到进阶的讲解就暂时结束啦后续随着博主的功力增加会不断更新(#^.^#),

写作不易,如果你认为博主写的不错!

请点赞、关注、评论给博主一个鼓励吧,您的鼓励就是博主前进的动力。

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

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

相关文章

java.sql.SQLException: Failed to fetch schema of XXX 问题

遇到问题&#xff1a;java.sql.SQLException: Failed to fetch schema of pay_record表 i.s.r.d.s.s.c.AbstractTableMetaCache : get table meta of the table pay_record error: Failed to fetch schema of pay_record 原因分析&#xff1a; springcloud项目中使用了se…

上海亚商投顾:沪指冲高回落 旅游板块全天强势

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日冲高回落&#xff0c;创业板指跌近1%&#xff0c;北证50指数跌超3%。旅游、零售板块全天强势&#xf…

python类继承之__init__函数覆盖问题

目录 1.问题描述 2.代码演示 3.总结 在Python这个广受欢迎的编程语言中&#xff0c;类继承是一项强大而精巧的特性。通过类继承&#xff0c;我们可以构建出更加灵活、可重用和易维护的代码&#xff0c;同时实现代码的模块化和扩展性。 但是如果对于熟悉C和java的人而言&…

R语言学习 case2:人口金字塔图

step1&#xff1a;导入库 library(ggplot2) library(ggpol) library(dplyr)step2&#xff1a;读取数据 data <- readxl::read_xlsx("data_new.xlsx", sheet 1) datareadxl::read_xlsx() 是 readxl 包中的函数&#xff0c;用于读取Excel文件。 step3&#xff1…

ckman:非常好用的ClickHouse可视化集群运维工具

概述 什么是ckman ckman&#xff0c;全称是ClickHouse Management Console&#xff0c; 即ClickHouse管理平台。它是由擎创科技数据库团队主导研发的一款用来管理和监控ClickHouse集群的可视化运维工具。目前该工具已在github上开源&#xff0c;开源地址为&#xff1a;github…

全网最详细丨2024年AMC8真题及答案来了

目录 前言 真题回忆 真题解析 结尾 前言 相信大家都已经知道今年AMC8出事情了吧&#xff0c;但最重要的还是要从中学到新知识。 听说今年考生被提前12分钟强制交卷了&#xff0c;肯定因为试题泄露了。 最新回复&#xff1a;我们这边已经退费了 真题回忆 需要word文档的请…

快速幂 算法

暴力算法 我们可以采用暴力算法 #include<bits/stdc.h> using namespace std; #define ll long long int main() {ll a, b, c;cin >> a >> b >> c;ll ans 1;for (ll i 1; i < b; i) {ans * a;}ans % c;cout << ans; } 不过这样肯定会超时…

计算机网络基础概念解释

1. 什么是网络 随着时代的发展&#xff0c;越来越需要计算机之间互相通信&#xff0c;共享软件和数据&#xff0c;即以多个计算机协同⼯作来完成业务&#xff0c;于是有了网络互连。 网络互连&#xff1a;将多台计算机连接在⼀起&#xff0c;完成数据共享。 数据共享本质是网络…

「 网络安全常用术语解读 」杀链Kill Chain详解

1. 简介 早在2009年&#xff0c;Lockheed Martin公司就提出了杀链(Kill Chain)理论&#xff0c;现在也称之为攻击者杀链(Attacker Kill Chain)。杀链其实就是攻击者进行网络攻击时所采取的步骤。杀链模型包括7个步骤&#xff1a;1侦察 -> 2武器化 -> 3交付 -> 4利用 …

不要长期把焦点放在让你烦恼的事情上

不要长期把焦点放在让你烦恼的事情上 在快节奏的生活中&#xff0c;我们经常会遇到各种各样让我们担心的事情。这些事情可能是工作上的压力&#xff0c;家庭中的矛盾&#xff0c;或者是个人的迷茫和困惑。然而&#xff0c;长期将焦点放在这些让我们烦恼的事情上&#xff0c;不…

PrestaShop购物系统 SQL注入漏洞复现(CVE-2023-30150)

0x01 产品简介 PrestaShop 是一个功能丰富,基于 PHP5 开发的 Web2.0 网上购物系统。PrestaShop 具有可定制,稳定等特点。整个系统只有 5.8MB,易于快速安装。 0x02 漏洞概述 PrestaShop 的部分主题中使用Leo Custom Ajax模块拓展,Leo Custom Ajax模块中可以在/modules/le…

JNPF低代码开发平台

一、关于低代码 JNPF平台在提供无代码&#xff08;可视化建模&#xff09;和低代码&#xff08;高度可扩展的集成工具以支持跨功能团队协同工作&#xff09;开发工具上是独一无二的。支持简单、快速地构建及不断改进Web端应用程序&#xff0c;可为整个应用程序的生命周期提供全…

HarmonyOS鸿蒙学习基础篇 - 项目目录和文件介绍

├── hvigor //存储购置信息的文件&#xff0c;主要用于发布打包 ├── idea //开发工具相关配置可忽略 ├── AppScope //工程目录 全局公共资源存放路径 │ └── resources │ │ └── base │ │ │ └── element //常亮存放 │ │ │ …

beego项目部署与热更新

1.开发自己的第一个项目 这里我引用的是在线聊天室&#xff0c;参考源码是https://github.com/beego/samples/tree/master/WebIM 在源码的基础上重新开发&#xff0c;整理项目发布到了liu289747235/WebIM 推荐下载源码&#xff1a;https://gitee.com/myselfyou/web-im 在线…

游戏开发中的噪声算法

一、噪声 噪声是游戏编程的常见技术&#xff0c;广泛应用于地形生成&#xff0c;图形学等多方面。 那么为什么要引入噪声这个概念呢&#xff1f;在程序中&#xff0c;我们经常使用直接使用最简单的rand()生成随机值&#xff0c;但它的问题在于生成的随机值太“随机”了&#xf…

爬虫之牛刀小试(八):爬取微博评论

今天爬取的是微博评论。 可以发现其特点是下一页评论的max_id在上一页中。 于是代码如下&#xff1a; import requests import json import re import time headers {User-Agent: ,"Cookie": "","Referer": "https://m.weibo.cn/detail/4…

【想要安利给所有人的开发工具】最强工具ChatGPT——分享一些使用经验

目录 &#x1f525;个人使用ChatGPT的经验 &#x1f525;如何使用ChatGPT 方法一 方法二 &#x1f525;&#x1f525;提问技巧分享 1、英语翻译员 2、面试官 3、javascript 控制台 4、Excel表格 5、作曲家 6、辩手 7、小说家 8、诗人 9、数学老师 10、网络安全…

2023江苏职教高考计算机技能考试--填空题解析

/*--------------- 【程序填空】 ----------------- 题目&#xff1a;验证任意一个大于1的正整数都可以找到 一串连续奇数&#xff0c;它们的和等于该整数的立方。 例如&#xff1a;4的立方等于64&#xff0c;6413579111315程序运行结果如下&#xff1a;3的立方等于27&#xff…

linux磁盘,分区,挂载等等

1. 修改磁盘分区的标签 例如&#xff1a;733be18b-7baf-d84c-879d-ca3db465f179太长了&#xff0c;修改一下。 linuxchenxiao:/media/linux/733be18b-7baf-d84c-879d-ca3db465f179$ 先 sudo blkid sudo blkid 找到你想修改的UUID(唯一标识符) /dev/sda1: UUID"733be…

Pytorch从零开始实战17

Pytorch从零开始实战——生成对抗网络入门 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——生成对抗网络入门环境准备模型定义开始训练总结 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#xff0c;Pytorch1.8cpu&#xf…