Mybatis框架学习
什么是mybatis?
mybatis是一款用于持久层的、轻量级的半自动化ORM框架,封装了所有jdbc操作以及设置查询参数和获取结果集的操作,支持自定义sql、存储过程和高级映射
mybatis用来干什么?
用于处理java和数据库的交互
使用mybatis的好处
- 与JDBC相比,减少了50%以上的代码量。
- MyBatis灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL可以写在XML里(还可以以注解方式写到Java代码中),从程序代码中彻底分离,降低耦合度,便于统一管理和优化,可重用。
- 提供XML标签,支持编写动态SQL语句(XML中使用 if, else 等)
使用mybatis
下载Mybatis的jar包:Releases · mybatis/mybatis-3 (github.com)
创建xml文件:mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments><mappers><mapper resource="org/mybatis/example/BlogMapper.xml"/></mappers>
</configuration>
修改内容:

SqlSessionFactoryBuilder
通过SqlSessionFactoryBuilder可创建多个SqlSessionFactory实例
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(new FileInputStream("mybatis-config.xml"));
SqlSessionFactory
通过SqlSessionFactory创建多个会话,SqlSession对象,每个会话就相当于我不同的地方登陆一个账号去访问数据库。
一般SqlSessionFactory只需要创建一次
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(new FileInputStream("mybatis-config.xml"));
SqlSession
使用 MyBatis 的主要 Java 接口就是 SqlSession。你可以通过这个接口来执行命令,获取映射器实例和管理事务。SqlSession实例可直接执行已映射的sql语句。
确保SqlSession关闭的标准模式:
//try-with-resource
try(SqlSession session = sqlSessionFactory.openSession()) {}
XML映射语句
基于XML映射语句,便可满足sqlsession的调用
例如简单的select语句
<?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="TestMapper"><select id="selectEmployee" resultType="com.test.entity.Employee">select * from employee where id = #{id}</select>
</mapper>
参数符号:#{id},这就告诉 MyBatis 创建一个预处理语句(PreparedStatement)参数,在 JDBC 中,这样的一个参数在 SQL 中会由一个?来标识,并被传递到一个新的预处理语句中.
MybatisUtil工具类
创建MybatisUtil工具类,以便集中创建SqlSession
public class MybatisUtil {private static SqlSessionFactory sqlSessionFactory;static {try {sqlSessionFactory = new SqlSessionFactoryBuilder().build(new FileInputStream("mybatis-config.xml"));} catch (FileNotFoundException e) {e.printStackTrace();}}/*** 获取一个新的会话* @param autoCommit 是否开启自动提交(跟JDBC是一样的,如果不自动提交,则会变成事务操作)* @return SqlSession对象*/public static SqlSession getSession(boolean autoCommit){return sqlSessionFactory.openSession(autoCommit);}
}
方便使用:
public class Main {public static void main(String[] args) throws FileNotFoundException {try(SqlSession session = MybatisUtil.getSession(true)) {TestMapper mapper = session.getMapper(TestMapper.class);}}
}
映射器接口
映射器是一些用来绑定映射语句的接口。创建com.test.mapper包,创建接口TestMapper。
这样做好处是将映射器的结果快速转换为需要的实体类,通过XML中的namespace绑定接口
- 全限定名(比如 “com.test.mapper.TestMapper")将被直接用于查找及使用。
<mapper namespace="com.test.mapper.TestMapper"><select id="selectEmployee" resultType="com.test.entity.Employee">select * from employee</select>
</mapper>
将接口与XML放在同包资源中,修改mybatis-config.xml文件
<mappers><mapper resource="com/test/mapper/TestMapper.xml"/></mappers>
XML配置属性typeAliases
typeAliases,类型别名,简化Mapper的缩写
<configuration><typeAliases><typeAlias type="com.test.entity.Employee" alias="Employee"/></typeAliases><environments default="development">........

或直接扫描包,默认别名为小写的开头
<typeAliases><package name="com.test.entity"/></typeAliases>
也可写注解来指定别名
@Alias("employee")
public class Employee {...
}
ResultMap
当类中定义的字段与数据库的字段不统一时,用ResultMap来映射到对应的实体
column:数据库中的字段,property:java中编写的字段名称
<mapper namespace="com.test.mapper.TestMapper"><resultMap id="Test" type="Employee"><result column="id" property="xxx"/></resultMap><select id="selectEmployee" resultMap="Test">....
多个构造器如何选择
当有多个构造器,优先选择满足全部字段的构造器,如果没有则报错

如果只有一个构造器,不管满足几个字段,都会调用
那如果就是没有满足的呢?那就要用constructor

<mapper namespace="com.test.mapper.TestMapper"><resultMap id="Test" type="Employee"><constructor><arg column="id" javaType="Integer"/><arg column="name" javaType="String"/></constructor><result column="id" property="xxx"/></resultMap>.......
注意:这样写的话,构造器中形参需要对象类型,比如如果用int不用Interger,会报错:

另外,这样写的话构造器中的字段并不会映射到,因为映射器已经交给构造器来处理了。
bug:绑定错误
Exception in thread “main” org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
解决:select中id与接口绑定错误,记得要一致


增删改查
创建接口实例
TestMapper mapper = session.getMapper(TestMapper.class);
TestMapper.xml中编写sql语句
<mapper namespace="com.test.mapper.TestMapper"><select id="getEmployeeId" resultType="Employee">select * from employee where id = #{id}</select><insert id="addEmployee" parameterType="Employee">insert into employee (id, name, sex, age, salary) values (#{id}, #{name}, #{sex}, #{age}, #{salary})</insert><delete id="deleteEmployee">delete from employee where id = #{id}</delete>
</mapper>

通过接口实例直接调用接口中的方法
update操作
mapper:
<update id="updateStudent" parameterType="student">update student set sex = #{sex} where sid = #{sid}
</update>
mapper接口:
int updateStudent(Student student);
测试:
Student student = mapper.getStudentSid(1940618805);
student.setSex("女");
mapper.updateStudent(student);
复杂查询
多表查询一对多:例如查询一个老师教多少个学生
collection:用于一对多关系,即实体里面放集合
<resultMap id="asTeacher" type="Teacher"><id column="tid" property="tid"/><result column="tname" property="name"/><collection property="studentList" ofType="Student"><id property="sid" column="sid"/><result column="name" property="name"/><result column="sex" property="sex"/></collection>
</resultMap> <select id="getTeacherByTid" resultMap="asTeacher">select *, teacher.name as tname from student inner join teach on student.sid = teach.sidinner join teacher on teacher.tid where teach.tid = #{tid}</select>
<id column="tid" property="tid"/>
id用于唯一标识一个老师
多表查询多对一:如果要求学生类增加一个老师属性,即根据教师id来找教师的所有学生
association:用于多对一关系
<resultMap id="test2" type="Student"><id column="sid" property="sid"/><result column="name" property="name"/><result column="sex" property="sex"/><association property="teacher" javaType="Teacher"><id column="tid" property="tid"/><result column="tname" property="name"/></association></resultMap><select id="selectStudent" resultMap="test2">select *, teacher.name as tname from student left join teach on student.sid = teach.sidleft join teacher on teach.tid = teacher.tid where teach.tid = #{tid}</select>
事务处理
自动提交关闭:
SqlSession session = MybatisUtil.getSession(false)
手动提交
session.commit();
动态SQL
if
test 为if的条件,如果为真,则拼接if标签里面的and语句,如查询学号是偶数的男同学
<select id="getStudentSid" resultType="student">select * from student where sid = #{sid}<if test="sid % 2 == 0">and sex = '男'</if></select>
choose,when,otherwise
类似于switch,case,default
<select><choose><when test = "">and...</when><when test = "">and...</when><otherwise>and...</otherwise></choose>
</select>
where
where元素只会在有子元素有返回的情况下才会插入where,并且如果子元素的开头是and,or,(显然sql语句中 where and…是语法错误的吧),where元素会将他们去除
select * from student<where><if test="sid != null">
<!-- and sid = #{sid}-->sid = #{sid}</if></where>
set
<update id="updateStudent">update student<set><if test="name != null">name = #{name}</if></set>where sid = #{sid}</update>
缓存机制
查询出的对象存入SqlSession的一级缓存,如果后续有相同操作,则之间从缓存中获取,不需要重新构造一个对象,提高效率
Student student = mapper.getStudentSid(1940618805);
Student student1 = mapper.getStudentSid(1940618805);
System.out.println(student1 == student); // true
但是,如果在该两次相同的操作中,对数据库内容进行了增,删,改操作,则会清除缓存
并且,每一个SqlSession会话的一级缓存是分开来的。即在不同的会话下,上述操作得到的不是同一个对象
一级缓存也叫做本地缓存,它只对一个会话的数据进行缓存。
要使用全局的缓存,是需要开启二级缓存。只需要在mapper文件中加上
<cache/>
<cacheeviction="FIFO"flushInterval="60000"size="512"readOnly="true"/>
这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。
开启二级缓存后,不同会话中连续的相同操作也会直接从缓存中获取对象。(同样的,如果在这两次操作之间对数据库内容进行了增,删,改操作,则会清除缓存)
但是,多个会话时,只有当一个会话结束了才会将数据从一级缓存写入二级缓存:
public class Main {public static void main(String[] args) throws FileNotFoundException {try(SqlSession session1 = MybatisUtil.getSession(true);SqlSession session2 = MybatisUtil.getSession(true)) {TestMapper mapper1 = session1.getMapper(TestMapper.class);TestMapper mapper2 = session2.getMapper(TestMapper.class);Student student1 = mapper1.getStudentSid(1940618806);Student student2 = mapper2.getStudentSid(1940618806);System.out.println(student1 == student2); // false 获取对象时会话未结束,二级缓存没有内容}}
}
注解开发
去除mapper xml文件,直接在mapper接口方法上写上注解
@Insert("insert into student(sid, name, sex) values(#{sid}, #{name}, #{sex})")
int addStudent(Student student);
使用注解开发需要修改mybatis配置文件的mappers
<mappers><mapper class="com.test.mapper.TestMapper"/>
<!-- <package name="com.test.mapper"/>--></mappers>
自定义映射规则
@Results
@Results({@Result(id = true, column = "sid", property = "sid"),@Result(column = "name", property = "name"),@Result(column = "sex", property = "sex")})@Select("select * from student where sid = #{sid}")Student getStudentSid(int sid);
一对多查询,如一个教师教的学生
@Many(select="")
这个就是一对多关系中联结查询的条件
@Results(value = {@Result(column = "tid", property = "tid"),@Result(column = "name", property = "name"),@Result(column = "tid", property = "studentList", many =@Many(select = "getStudentByTid"))})@Select("select * from teacher where tid = #{tid}")Teacher getTeacherByTid(int tid);@Select("select * from student inner join teach on student.sid = teach.sid where tid = #{tid}")List<Student> getStudentByTid(int tid);
@Param()
当select语句有多个参数条件时,使用@Param()
@Select("select * from student where sid = #{sid} and sex = #{sex}")Student getStudentBySidAndSex(@Param("sid")int sid, @Param("sex")String sex);
否则报错
### Error querying database. Cause: org.apache.ibatis.binding.BindingException: Parameter 'sid' not found. Available parameters are [arg1, arg0, param1, param2]
这是因为多个参数时,mybatis并不知道这些属性是哪里来的,“Parameter xxx not found”
相关文章:
Mybatis框架学习
什么是mybatis? mybatis是一款用于持久层的、轻量级的半自动化ORM框架,封装了所有jdbc操作以及设置查询参数和获取结果集的操作,支持自定义sql、存储过程和高级映射 mybatis用来干什么? 用于处理java和数据库的交互 使用mybat…...
基于微信小程序的电影院订票系统设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言运行环境说明用户微信小程序端的主要功能有:管理员的主要功能有:具体实现截图详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考论文参考源码获取 前言 💗博主介绍&…...
LeetCode-热题100-笔记-day32
二分查找 今日刷到二分查找,以前做过的题忘的一干二净;庆幸自己用新的方法做了出来两道“中等”题;(我都能做出来我认为应该标“简单”)由于之前题的难度基本在抄答案,所以停更几天。今天没抄答案就更新一…...
STP生成树协议基本配置示例---STP逻辑树产生和修改
STP是用来避免数据链路层出现逻辑环路的协议,运行STP协议的设备通过交互信息发现环路,并通过阻塞特定端口,最终将网络结构修剪成无环路的树形结构。在网络出现故障的时候,STP能快速发现链路故障,并尽快找出另外一条路径…...
Java版企业电子招标采购系统源码—企业战略布局下的采购寻源
项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及审…...
华纳云:SQLserver配置远程连接的方法是什么
在 SQL Server 中配置远程连接涉及一些步骤,包括启用远程连接、配置网络协议、设置防火墙规则和授权远程访问。以下是一些配置远程连接的主要步骤: 启用远程连接: 打开 SQL Server Management Studio(SSMS)并连接到你的…...
CryptoCTF easy
文章目录 2023suctionBlue Office 2022Baphomet 2023 suction 题目描述: from Crypto.Util.number import * from flag import flagdef keygen(nbit, r):while True:p, q [getPrime(nbit) for _ in __]e, n getPrime(16), p * qphi (p - 1) * (q - 1)if GCD(e…...
计算机视觉技术的革新:医疗领域的应用
近年来,计算机视觉技术在医疗领域引起了广泛的关注和应用。通过将计算机视觉与医疗技术相结合,我们可以实现更准确、高效的医疗诊断和治疗,为患者提供更好的医疗服务。 首先,计算机视觉在医疗图像分析中的应用是其中的一个重要方…...
python找出文件夹里文件名以特定字符结尾的文件并移动到另一个目录
python找出文件夹里文件名以特定字符结尾的文件并移动到另一个目录 代码 import os import shutil# 源文件夹路径 source_folder "./data/deep/test"# 目标文件夹路径 target_folder "./data/deep/A"# 确保目标文件夹存在,如果不存在则创建…...
面试官问:大量的 TIME_WAIT 状态 TCP 连接,对业务有什么影响?怎么处理?
几个方面: 问题描述:什么现象?什么影响? 问题分析 解决方案 底层原理 1.问题描述 模拟高并发的场景,会出现批量的 TIME_WAIT 的 TCP 连接: 短时间后,所有的 TIME_WAIT 全都消失࿰…...
前端就业宝典---目录
工作时候扭螺丝,面试时候造火箭,现状就是如此。不管是背八股文,还是掌握了知识的精华,对答如流才是硬道理。本专栏就是要集具前端精华,规范、算法、架构、封装、原理等一并汇集,让前端的小伙伴有个思路。 大剑师的微信 gis-dajianshi, 欢迎一起交流,并非常期望您能够提…...
Uniboot 系列光纤跳线简介
飞速(FS)Uniboot 系列光纤跳线产品质量可靠,性能优良,可满足数据中心的各种需求。其中,包括LC、CS™、MDC 和 SN 在内的不同类型的连接器能够满足不同应用的特定需求。下面将进一步介绍飞速(FS)…...
【面试题】Promise只会概念远远不够,还需这17道题目巩固!
前端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 表妹一键制作自己的五星红旗国庆头像,超好看 在学习Promise相关题目之前,我们先做一些知识的回顾:JavaScript 是一门单…...
互联网医院牌照|互联网医院牌照审批流程和材料
随着科技的不断进步和社会的发展,互联网医院已经成为了当前的热点。而互联网医院的准入门槛自然也就越来越高。如果您计划成立一个互联网医院,您需要了解申请互联网医院牌照所需要注意的方面以及申请的流程。 一、资质申请前的准备 1、立项阶段准备 在立…...
第五章:C语言的数组
文章目录 1、数组的理解2、各类数组的定义3、变长数组4、字符数组 1、数组的理解 一维数组:比如定义一个int a[3];,那么可以将其看成两部分,a【3】为①,int为②。意思就是有一个数组名字为a,里面包含3个(池࿰…...
Spring面试题3:说一说MVC框架的底层实现
该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:说一说MVC框架的底层实现 MVC(Model-View-Controller)是一种软件设计模式,常被用于构建用户界面和应用程序的架构。MVC框架的底层实现可以分为…...
云原生周刊:K8s 的 13 个最佳开源监控工具
开源项目推荐 Silver Surfer 该项目旨在检查 Kubernetes 对象的 API 版本兼容性,并为其提供迁移路径,以便为集群升级做好准备。 Actions Runner Controller Actions Runner Controller (ARC) 是一个 Kubernetes 操作器,可为 GitHub Actio…...
怎么克服一篇论文写作前的恐惧感?
作者 代陈锐 中国科学技术大学生命科学与医学部在读博士生,主要探究生理和病理过程中组蛋白翻译后修饰的调控机制。 1. 引言 在我们开始一篇文章的撰写时,往往不知如何下笔或是不停否认自己撰写的内容,最终的结果自然是撰写效率低而且陷入自我纠结。在这里我通过结合平时…...
Linux 安全 - Credentials
文章目录 一、简介1.1 Objects1.2 Object ownership1.3 The objective context1.4 Subjects1.5 The subjective context1.6 Actions1.7 Rules, access control lists and security calculations 二、Types of Credentials2.1 Traditional UNIX credentials2.2 Capabilities2.3 …...
网站服务器怎么部署
网站服务器怎么部署 1. 选择合适的服务器:根据网站的需求和流量,选择合适的服务器,包括硬件配置、操作系统和网络环境等。 2. 安装操作系统:根据服务器硬件配置选择合适的操作系统,并进行安装和配置,包括安…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...
AT模式下的全局锁冲突如何解决?
一、全局锁冲突解决方案 1. 业务层重试机制(推荐方案) Service public class OrderService {GlobalTransactionalRetryable(maxAttempts 3, backoff Backoff(delay 100))public void createOrder(OrderDTO order) {// 库存扣减(自动加全…...
iOS 项目怎么构建稳定性保障机制?一次系统性防错经验分享(含 KeyMob 工具应用)
崩溃、内存飙升、后台任务未释放、页面卡顿、日志丢失——稳定性问题,不一定会立刻崩,但一旦积累,就是“上线后救不回来的代价”。 稳定性保障不是某个工具的功能,而是一套贯穿开发、测试、上线全流程的“观测分析防范”机制。 …...
