当前位置: 首页 > news >正文

Mybatis框架学习

什么是mybatis?

mybatis是一款用于持久层的、轻量级的半自动化ORM框架,封装了所有jdbc操作以及设置查询参数和获取结果集的操作,支持自定义sql、存储过程和高级映射

mybatis用来干什么?

用于处理java和数据库的交互

使用mybatis的好处

  1. 与JDBC相比,减少了50%以上的代码量。
  2. MyBatis灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL可以写在XML里(还可以以注解方式写到Java代码中),从程序代码中彻底分离,降低耦合度,便于统一管理和优化,可重用。
  3. 提供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&#xff1f; mybatis是一款用于持久层的、轻量级的半自动化ORM框架&#xff0c;封装了所有jdbc操作以及设置查询参数和获取结果集的操作&#xff0c;支持自定义sql、存储过程和高级映射 mybatis用来干什么&#xff1f; 用于处理java和数据库的交互 使用mybat…...

基于微信小程序的电影院订票系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言运行环境说明用户微信小程序端的主要功能有&#xff1a;管理员的主要功能有&#xff1a;具体实现截图详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考论文参考源码获取 前言 &#x1f497;博主介绍&…...

LeetCode-热题100-笔记-day32

二分查找 今日刷到二分查找&#xff0c;以前做过的题忘的一干二净&#xff1b;庆幸自己用新的方法做了出来两道“中等”题&#xff1b;&#xff08;我都能做出来我认为应该标“简单”&#xff09;由于之前题的难度基本在抄答案&#xff0c;所以停更几天。今天没抄答案就更新一…...

STP生成树协议基本配置示例---STP逻辑树产生和修改

STP是用来避免数据链路层出现逻辑环路的协议&#xff0c;运行STP协议的设备通过交互信息发现环路&#xff0c;并通过阻塞特定端口&#xff0c;最终将网络结构修剪成无环路的树形结构。在网络出现故障的时候&#xff0c;STP能快速发现链路故障&#xff0c;并尽快找出另外一条路径…...

Java版企业电子招标采购系统源码—企业战略布局下的采购寻源

项目说明 随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&#xff0c;以及审…...

华纳云:SQLserver配置远程连接的方法是什么

在 SQL Server 中配置远程连接涉及一些步骤&#xff0c;包括启用远程连接、配置网络协议、设置防火墙规则和授权远程访问。以下是一些配置远程连接的主要步骤&#xff1a; 启用远程连接&#xff1a; 打开 SQL Server Management Studio&#xff08;SSMS&#xff09;并连接到你的…...

CryptoCTF easy

文章目录 2023suctionBlue Office 2022Baphomet 2023 suction 题目描述&#xff1a; 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…...

计算机视觉技术的革新:医疗领域的应用

近年来&#xff0c;计算机视觉技术在医疗领域引起了广泛的关注和应用。通过将计算机视觉与医疗技术相结合&#xff0c;我们可以实现更准确、高效的医疗诊断和治疗&#xff0c;为患者提供更好的医疗服务。 首先&#xff0c;计算机视觉在医疗图像分析中的应用是其中的一个重要方…...

python找出文件夹里文件名以特定字符结尾的文件并移动到另一个目录

python找出文件夹里文件名以特定字符结尾的文件并移动到另一个目录 代码 import os import shutil# 源文件夹路径 source_folder "./data/deep/test"# 目标文件夹路径 target_folder "./data/deep/A"# 确保目标文件夹存在&#xff0c;如果不存在则创建…...

面试官问:大量的 TIME_WAIT 状态 TCP 连接,对业务有什么影响?怎么处理?

几个方面&#xff1a; 问题描述&#xff1a;什么现象&#xff1f;什么影响&#xff1f; 问题分析 解决方案 底层原理 1.问题描述 模拟高并发的场景&#xff0c;会出现批量的 TIME_WAIT 的 TCP 连接&#xff1a; 短时间后&#xff0c;所有的 TIME_WAIT 全都消失&#xff0…...

前端就业宝典---目录

工作时候扭螺丝,面试时候造火箭,现状就是如此。不管是背八股文,还是掌握了知识的精华,对答如流才是硬道理。本专栏就是要集具前端精华,规范、算法、架构、封装、原理等一并汇集,让前端的小伙伴有个思路。 大剑师的微信 gis-dajianshi, 欢迎一起交流,并非常期望您能够提…...

Uniboot 系列光纤跳线简介

飞速&#xff08;FS&#xff09;Uniboot 系列光纤跳线产品质量可靠&#xff0c;性能优良&#xff0c;可满足数据中心的各种需求。其中&#xff0c;包括LC、CS™、MDC 和 SN 在内的不同类型的连接器能够满足不同应用的特定需求。下面将进一步介绍飞速&#xff08;FS&#xff09;…...

【面试题】Promise只会概念远远不够,还需这17道题目巩固!

前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 表妹一键制作自己的五星红旗国庆头像&#xff0c;超好看 在学习Promise相关题目之前&#xff0c;我们先做一些知识的回顾&#xff1a;JavaScript 是一门单…...

互联网医院牌照|互联网医院牌照审批流程和材料

随着科技的不断进步和社会的发展&#xff0c;互联网医院已经成为了当前的热点。而互联网医院的准入门槛自然也就越来越高。如果您计划成立一个互联网医院&#xff0c;您需要了解申请互联网医院牌照所需要注意的方面以及申请的流程。 一、资质申请前的准备 1、立项阶段准备 在立…...

第五章:C语言的数组

文章目录 1、数组的理解2、各类数组的定义3、变长数组4、字符数组 1、数组的理解 一维数组&#xff1a;比如定义一个int a[3];,那么可以将其看成两部分&#xff0c;a【3】为①&#xff0c;int为②。意思就是有一个数组名字为a&#xff0c;里面包含3个&#xff08;池&#xff0…...

Spring面试题3:说一说MVC框架的底层实现

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:说一说MVC框架的底层实现 MVC(Model-View-Controller)是一种软件设计模式,常被用于构建用户界面和应用程序的架构。MVC框架的底层实现可以分为…...

云原生周刊:K8s 的 13 个最佳开源监控工具

开源项目推荐 Silver Surfer 该项目旨在检查 Kubernetes 对象的 API 版本兼容性&#xff0c;并为其提供迁移路径&#xff0c;以便为集群升级做好准备。 Actions Runner Controller Actions Runner Controller (ARC) 是一个 Kubernetes 操作器&#xff0c;可为 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. 选择合适的服务器&#xff1a;根据网站的需求和流量&#xff0c;选择合适的服务器&#xff0c;包括硬件配置、操作系统和网络环境等。 2. 安装操作系统&#xff1a;根据服务器硬件配置选择合适的操作系统&#xff0c;并进行安装和配置&#xff0c;包括安…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

OD 算法题 B卷【正整数到Excel编号之间的转换】

文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的&#xff1a;a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...