当前位置: 首页 > 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;包括安…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...