Mybatis 笔记

news2025/4/6 2:08:53

一、mybatis简介

1.1 框架概念

软件的半成品,完成软件开发过程中的通用操作,实现特定的功能,从而简化开发人员在软件开发中的步骤,提升开发效率。

1.2 常用框架

  • MVC框架:简化servlet的开发步骤,与前端交互
    • struct2
    • springMVC
  • 持久层框架:完成数据库操作的框架,与数据库交互
    • mybatis
    • hibernate
  • 胶水框架:Spring --- 负责协同MVC和持久层

1.3 mybatis介绍

mybatis是半自动的ORM框架,提供了实体类和数据表的映射关系,通过映射文件配置,实现对象的持久化。

  • 半自动:封装度不高,SQL语句还需要自己写,比较适合处理复杂的SQL,多表联查等(hibernate是全自动)
  • ORM(Object Relaitional Mapping):对象关系映射,将Java中的一个对象与表中的一行记录一一对应。

1.4 mybatis 的特点

  • 支持自定义SQL,存储过程
  • 对原有的JDBC进行封装,几乎消除了所有的JDBC代码,开发者只需要关注SQL本身
  • 支持XML和注解配置的方式自动完成ORM操作,实现结果映射。

二、mybatis框架部署

  1. 创建一个maven项目
  2. 在pom.xml中添加依赖(mybatis依赖,mysql driver依赖)
  3. 创建mybatis主配置文件
    1. resource目录下新建mybatis-config.xml配置文件
    2. mybatis-config.xml文件中配置数据库连接信息
pom中的依赖
<dependencies>
	 <dependency>
		 <groupId>junit</groupId>
		 <artifactId>junit</artifactId>
		 <version>4.11</version>
		 <scope>test</scope>
	</dependency>
	 <dependency>
		 <groupId>org.mybatis</groupId>
		 <artifactId>mybatis</artifactId>
		 <version>3.5.1</version>
	</dependency>
	 <dependency>
		 <groupId>mysql</groupId>
		 <artifactId>mysql-connector-java</artifactId>
		 <version>5.1.9</version>
	 </dependency>
 </dependencies>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
 <!--配置 mybatis 环境-->
 <environments default="mysql">
	 <!--id:数据源的名称-->
	 <environment id="mysql">
	 <!--配置事务类型:使用 JDBC 事务(使用 Connection 的提交和回滚)-->
	 <transactionManager type="JDBC"/>
	 <!--数据源 dataSource:创建数据库 Connection 对象 type: POOLED 使用数据库的连接池 -->
	 <dataSource type="POOLED">
		<!--连接数据库的四个要素-->
		 <property name="driver" value="com.mysql.jdbc.Driver"/>
		 <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
		 <property name="username" value="root"/>
		 <property name="password" value="123456"/>
	 </dataSource>
	 </environment>
 </environments>
 <mappers>
 <!--告诉 mybatis 要执行的 sql 语句的位置,建议多个映射文件写在一个文件夹下面-->
 <mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
 </mappers>
</configuration>
支持中文的 url
jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8

三、mybatis框架使用

  1. 创建表结构信息
  2. domain包中创建实体类,属性和表属性对应
  3. dao包中创建接口,定义操作数据库的方法
  4. resource包下创建一个mappers文件夹,创建dao包中接口的映射文件
  5. 映射文件添加到主配置文件中,告诉mybatis要执行的SQL的位置。
  6. 测试用例
<?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">
<!--
 namespace:必须有值,自定义的唯一字符串 
 推荐使用:dao 接口的全限定名称 
-->
<mapper namespace="com.bjpowernode.dao.StudentDao">
	 <!--
	 <select>: 查询数据, 标签中必须是 select 语句
	 id: sql 语句的自定义名称,推荐使用 dao 接口中方法名称, 
	 使用名称表示要执行的 sql 语句
	 resultType: 查询语句的返回结果数据类型,使用全限定类名 
	 -->
	 <select id="selectStudents" resultType="com.bjpowernode.domain.Student">
	 <!--要执行的 sql 语句-->
	 select id,name,email,age from student
	 </select>
</mapper>

四、mybatis 的动态SQL

动态SQL:根据查询条件动态完成SQL的拼接

4.1 动态SQL <if>

对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片断拼接到其所在的 SQL 语句中。

 语法:
 <if test="条件"> sql 语句的部分 </if>

<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
	 select id,name,email,age from student
	 where 1=1
	 <if test="name != null and name !='' ">
		and name = #{name}
	 </if>
	 <if test="age > 0 ">
		and age &gt; #{age}
	 </if>
</select>

# 注意where条件后面的1=1

4.2 动态SQL <where>

if标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。因为,若 where 后 的所有条件均为 false,而 where 后若又没有 1=1 子句,则 SQL 中就会只剩下一个空的 where,SQL 出错。但当数据量很大时,会 严重影响查询效率。

使用<where/>标签,在有条件查询时,会自动加上where子句,没有条件查询也不会添加where子句,需要注意的是,第一个<if/>标签中的SQL片段,既可以加and,也可以不加and,而其他<if/>标签中的SQL片段必须加上and,但是建议都加上。

 语法:
 <where> 其他动态SQL </where>

<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student
	 <where>
		 <if test="name != null and name !='' ">
			and name = #{name}
		 </if>
		 <if test="age > 0 ">
			and age &gt; #{age}
		 </if>
	 </where>
</select>

4.3 动态SQL之 <trim>

<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student
	 <trim prefix="where" prefixOverrides="and | or" suffix="order by age">
		 <if test="name != null and name !='' ">
			and name = #{name}
		 </if>
		 <if test="age > 0 ">
			and age &gt; #{age}
		 </if>
	 </trim>
</select>

# prefix 前缀
# prefixOverrides 第一个是and或者or,就自动去掉
# suffix 后缀

4.4 动态SQL之 foreach

语法
 <foreach collection="集合类型" open="开始的字符" close="结束的字符" 
	item="集合中的成员" separator="分隔符">
	#{stuid}
 </foreach>



<select id="selectStudentForList" resultType="com.bjpowernode.domain.Student">
	 select id,name,email,age from student
	 <if test="list !=null and list.size > 0 ">
		 where id in
		 <foreach collection="list" open="(" close=")" 
			item="stuid" separator=",">
			#{stuid}
		 </foreach>
	 </if>
</select>

五、一些常见的问题

5.1 mybatis的优缺点

  • 优点:
    • 半ORM的框架,封装了JDBC代码,开发者只需要关注如何编写SQL,减少了开发难度
    • SQL写在XML里面,保证了SQL和代码的解耦,便于SQL的统一管理。支持编写动态SQL语句,保证SQL的可重用性
    • 很好的与各种数据库兼容
    • 能够与spring很好的集成
  • 缺点
    • SQL编写工作量大,尤其是多表联查的时候,SQL的编写较为复杂
    • SQL语句依赖数据库,移植性差,不能随意更换数据库。

5.2 #{}和${}的区别是什么?

  1. 编译过程
    1. #{} 是占位符,SQL会在执行前进行预编译,将#{}对应的内容替换为 ? 调用prepareSatement的set方法进行赋值
    2. ${}是拼接符,字符的替换,相当于对应的内容append
  2. 是否自动加引号
    1. #{}对应的变量会自动加上引号
    2. ${}对应的变量不会自动加引号,因此编写的时候要注意手动加引号
  3. 安全性
    1. #{} 因为是预编译的占位符,因此能防止SQL注入
    2. ${}则不能防止SQL注入

5.3 mybatis中 dao接口和mapper.xml文件中的SQL是如何建立关联的?

mapper.xml其实是对dao接口的实现,mapper.xml中的namespace对应的是dao接口的全限定名。

1、解析XML: mybatis初始化SqlSessionFactoryBean的时候,会找到mapperLocations路径去解析里面所有的XML文件。

  • 创建SqlSource:把每个SQL封装成SqlSource对象(分为静态SQL--字符串和动态SQL---SQLNode)
  • 创建MappedStatement:每个SQL标签就对应一个MappedStatement对象,包括两个属性。创建完MappedStatement对象,就把他缓存到Configuration对象中,基本所有的配置信息都维护在Configuration 
    • id: 全限定类名加方法名组成的id
    • sqlSource:当前SQL标签对应的SqlSource对象

 2、Dao接口代理

  • dao的初始化
    • SqlSessionFactoryBuilder 的build方法去解析配置文件,得到一个SqlSessionFactory工厂对象,传入的参数是一个inputStream流,其实就是去读取mybatis的主配置文件和mapper.xml  ---- 同时将所有的配置信息都缓存在Configuration对象中
    • factory.openSession() 建立连接,获取事务管理配置,创建事务管理对象
    • sqlSession.getMapper(dao.class) ---- 通过jdk动态代理产生dao代理对象。

 

5.4 Dao接口里面的方法,参数不同的时候可以重载吗?

Mapper接口里的方法,是不能重载的,因为mybatis是使用 全限名+方法名 的保存和寻找策略;当调用接口方法时,通过 “接口全限名+方法名”拼接字符串作为key值,可唯一定位一个MapperStatement,因为在Mybatis中,每一个SQL标签,都会被解析为一个MapperStatement对象。如果重载,方法名一致,就会导致key value的覆盖。

5.5 Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?

记住mybatis是使用 全限名+方法名 的保存和寻找策略,如果不同的xml的namespace不同,那么id是可以重复的。

5.6 mybatis中的分页?

  • 原生的limit分页:
    • 需要在SQL中编写limit关键字,然后传入分页参数进行分页
    • 缺点是编写SQL复杂
  • RowBounds分页:
    • 是mybatis中内置的一个处理分页的类,可以不需要在映射SQL中写limit关键字,自动给我们拼接,使用方便
    • 不适用于处理数据量较大的场景。
  • 拦截器插件分页(如pageHelper)

 

5.7 mybatis插件运行原理

mybatis框架下,我们可以基于插件机制实现分页,分表和监控等功能。

mybatis的四大组件:ExecutorStatementHandlerParameterHandlerResultSetHandler,mybatis支持用插件对四大核心对象进行拦截,其实,插件就是拦截器,用来增强核心对象的功能,增强功能的本质是借助动态代理实现的。

Mybatis编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件,使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。

插件运行原理:

  1. 每个对象创建出来不是直接返回,而是调用了interceptorChain.pluginAll(parameterHandler);
  2. 拦截器链是mybatis初始化时创建出来的,保存了所有的拦截器
  3. 遍历所有拦截器,调用intercept.plugin(target)返回封装后的target对象
    1. interceptor.plugin(target)中调用了Plugin.warp(target,this)
    2. Plugin类实现了InvocationHandler接口,也就是说调用Plugin类的方法最终会调用Plugin的invoke()方法的实现
    3. invoke()方法最终会回调Interceptor的抽象方法intercept()
    4. intercept()方法具体实现是我们自己
  4. 我们可以使用插件为目标对象创建一个代理对象,AOP四大组件,然后拦截四大对象的每次执行

Mybatis插件原理总结 - 寒天峰 - 博客园

5.8 mybatis的延迟加载?

mybatis的延迟加载也称为懒加载,是指在进行表的管理查询时,只查询需要使用的数据,关联的数据不适用则不查询,也称为按需查询。

如进行一对多查询时,只查询出一方,当程序需要多方的数据时,mybatis在发出SQL语句进行查询,这样就可以减少数据库的压力。

mybatis延迟加载的条件:resultMap实现高级映射,如使用association、collection实现一对一以及一对多映射;关联对象的查询时子查询,多表连接查询则不行。

延迟加载好处:先从单表查询,需要时在从关联表查询,大大提高了数据库的性能。

延迟加载的原理:

本质是通过动态代理的方式,创建目标对象的代理对象,调用目标方法时(getting方法),进入拦截器方法,⽐如调⽤ a.getB().getName() ⽅法,进⼊拦截器的 invoke(...) ⽅法,发现 a.getB() 需要延迟加载时(为null时),那么就会单独发送事先保存好的查询关联 B 对象的 SQL ,把 B 查询上来,然后调⽤ a.setB(b) ⽅法,于是 a 对象 b 属性就有值了,接着完成 a.getB().getName() ⽅法的调⽤。这就是延迟加载的基本原理。

5.9 mybatis的缓存

mybatis提供了对缓存的支持 ,分为一级缓存和二级缓存。

  • 一级缓存是SqlSession级别的缓存,操作数据库时需要构造SqlSession对象,一级缓存主要是SqlSession内部共享,不同SqlSession之间缓存互不影响
  • 二级缓存是namespace级别的缓存,多个SqlSession去操作同一个mapper中的SQL语句时,可以共用二级缓存。

5.9.1 一级缓存

SqlSession是一个接口,提供了一些CRUD的方法,其默认实现类为DefaultSqlSession,DefaultSqlSession 类持有 Executor 接口对象,而 Executor 的默认实现是 BaseExecutor 对象,每个 BaseExecutor 对象都有一个 PerpetualCache 缓存,是一个hashMap。

用户发起查询时,根据当前执行语句生成MappedStatement,在 Local Cache 进行查询,如果缓存命中的话,直接返回结果给用户,如果缓存没有命中的话,查询数据库,结果写入 Local Cache,最后返回结果给用户。

 

一级缓存配置:
<setting name="localCacheScope" value="SESSION"/>

value两个选项
SESSION 默认级别 一个 MyBatis 会话中执行的所有语句,都会共享这一个缓存
STATEMENT,可以理解为缓存只对当前执行的这一个 Statement 有效。

 一级缓存总结:

  • 一级缓存生命周期和SqlSession一致
  • 一级缓存结构是一个hashmap
  • 一级缓存缓存的是对象(user1 == user2 会打印为true,代码里对user1属性修改,会影响user2,但是不会影响数据库。)
  • 一个SqlSession内部的更新操作会导致一级缓存失效
  • 一级缓存适用范围为一个SqlSession 内部,分布式环境下或者有多个SqlSession 时,其他SqlSession 的写操作会导致脏数据,建议缓存级别设置为statement

5.9.2 二级缓存

如果多个SqlSession需要共享缓存,则需要使用到二级缓存,二级缓存默认是不开启的,开启之后,会使用CachingExecutor 装饰 Executor,进入一级缓存的查询流程前,先在 CachingExecutor 进行二级缓存的查询

二级缓存数据存储的介质不一定在内存中,也有可能在硬盘中,从硬盘读取的时候需要反序列化,因此相关pojo类都需要实现Serializable 序列化接口

 二级缓存总结:

  • 二级缓存是 namespace 级别,实现了 SqlSession 之间缓存数据的共享
  • 二级缓存缓存的是数据(user1 == user2 会打印为false)
  • 其他SqlSession的更新操作,会导致二级缓存失效,从而当前SqlSession查询会走数据库
  • 多表查询时,极大可能出现脏数据,安全使用条件苛刻(通常我们会为每个单表创建单独的映射文件,由于 MyBatis 的二级缓存是基于 namespace 的,多表查询语句所在的 namspace 无法感应到其他 namespace 中的语句对多表查询中涉及的表进行的修改,引发脏数据问题)

mybatis缓存总结:

实际生产环境一般都会关闭mybatis的缓存,因为这个缓存真的很鸡肋啊。

对于一级缓存:多个SqlSession或者分布式环境,容易产生脏数据,增删改操作多的服务,清除一级缓存也很麻烦

对于二级缓存:虽然解决了SqlSession之间缓存数据共享问题,但是多表查询情况,不同namespace之间无法感应到变化,引发脏数据,基于cache ref 解决的话导致缓存粒度变粗,并且增加了开发成本。

因此,直接使用redis等分布式缓存成本会更低,安全性也会更高。

5.10 mybatis如何将SQL执行结果封装为目标对象并返回的?有哪些映射方式?

  1. 使用resultMap标签,column对应表字段,property对应对象的属性名,并将定义的resultMap标签作为select标签的 resultMap 属性赋值进去
  2. 使用sql列的别名功能,将列的别名书写为对象属性名。
 mapper 文件:
<!-- 创建 resultMapid:自定义的唯一名称,在<select>使用type:期望转为的 java 对象的全限定名称或别名 -->
<resultMap id="studentMap" type="com.bjpowernode.domain.Student">
	 <!-- 主键字段使用 id -->
	 <!-- column对应表字段,property对应对象的属性名 -->
	 <id column="id" property="id" /> 
	 <!--非主键字段使用 result-->
	 <result column="name" property="name"/>
	 <result column="email" property="email" />
	 <result column="age" property="age" />
</resultMap>
<!--resultMap: resultMap 标签中的 id 属性值-->
<select id="selectUseResultMap" resultMap="studentMap">
	 select id,name,email,age from student where name=#{queryName} or age=#{queryAge}
</select>

 5.11 mybatis动态SQL的用处?

根据查询条件动态完成SQL的拼接,实现SQL的复用

执行原理是根据表达式的值,完成逻辑判断,并拼接SQL。

5.12 如何获取自动生成的主键值?主键回填?

<insert id=”insertname” usegeneratedkeys=”true” keyproperty=”id”>
     insert into names (name) values (#{name})
</insert>

5.13  在mapper中如何传递多个参数?

  • 用#{arg0}、#{arg1}...传递参数,但是要注意顺序不能错,一般不用
  • 用param注解
  • 用map
  • 用Javabean

public interface usermapper {
   user selectuser(@param(“username”) string username,
                    @param(“hashedpassword”) string hashedpassword);
}

5.14 一对一,一对多查询

1、一对一关联查询 association

<select id="getClass" parameterType="int" resultMap="ClassesResultMap">  
	select * from class c,teacher t where c.teacher_id=t.t_id and c.c_id=#{id}  
</select>  

<resultMap type="com.lcb.user.Classes" id="ClassesResultMap">  
	<!-- 实体类的字段名和数据表的字段名映射 -->  
	<id property="id" column="c_id"/>  
	<result property="name" column="c_name"/>  
	<association property="teacher" javaType="com.lcb.user.Teacher">  
		<id property="id" column="t_id"/>  
		<result property="name" column="t_name"/>  
	</association>  
</resultMap> 

2、一对多关联查询 collection

<resultMap type="com.lcb.user.Classes" id="ClassesResultMap2">  
	<id property="id" column="c_id"/>  
	<result property="name" column="c_name"/>  
	<association property="teacher" javaType="com.lcb.user.Teacher">  
		<id property="id" column="t_id"/>  
		<result property="name" column="t_name"/>  
	</association>  

	<collection property="student" ofType="com.lcb.user.Student">  
		<id property="id" column="s_id"/>  
		<result property="name" column="s_name"/>  
	</collection> 
</resultMap> 

5.15  一对一有几种查询方式,怎么操作的 

1、联合查询,见5.14,在resultMap中配置association节点

2、子查询,先查一个表,根据这个表的结果的外键id,在去查另外一个表的数据。也是通过association配置,但是另一个表的查询通过select属性配置,而不是写在SQL中。

<association property="teacher" javaType="com.lcb.user.Teacher" select="子查询id"/>  

 一对多查询,就是把association节点变成collection节点

5.16 什么是mybatis的接口绑定?有哪些实现方式?

接口绑定,就是在mybatis中任意定义接口,然后把接口中的方法和SQL进行绑定,我们直接调用接口方法就可以。

接口绑定有两种实现方式

  • 注解绑定,在接口的方法上添加@select,@update等注解,适合简单的SQL
  • xml绑定,指定xml映射文件的namespace为接口全路径名,适合较为复杂的SQL

5.17 mybatis 和 hibernate有哪些不同?

  • mybatis
    • 半ORM框架,需要自己编写SQL
    • 直接编写原生态SQL,可以严格控制SQL执行,灵活度高
    • 无法做到数据库无关性,实现支持多种数据库软件需要自定义多套SQL映射文件
  • hibernate
    • 全orm框架,无需编写SQL
    • 对象/关系映射能力强
    • 数据无关性好,对关系模型要求高的软件,使用hibernate开发可以节省代码提高效率。

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

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

相关文章

java实现oracle和mysql的group by分组功能|同时具备max()/min()/sum()/case when 函数等功能

一、前言oracle和mysql的group by 分组功能大家应该清楚&#xff0c;那如何使用java实现同样的功能呢比如下面这个表idnameagemathEnglish10yujianlin2092.5103ww84102520102611036310351020我们需要按id分组&#xff0c;求最大age和math累计成绩我们的sql应该这样写select id,…

Linux下的安装环境

目录 软件安装常识 Linux软件安装生态 Linux软件生态的本土化 yum的三板斧&#xff1a;查找、安装、卸载 yum补充的3个小知识 软件安装常识 我们知道Linux下有一条命令可以下载安装指令&#xff0c;那就是yum。在了解yum之前得先说一下Linux的整体安装环境。 Linux下用y…

每日学术速递2.1

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.Cv 1.SeaFormer: Squeeze-enhanced Axial Transformer for Mobile Semantic Segmentation 标题&#xff1a;SeaFormer:用于移动语义分割的挤压增强型轴向变换器 作者&#xff1a; Qian…

从 await-to-js 到 try-run-js

之前在做 code review 时候发现有同事使用 try catch 包装了一堆异步代码&#xff0c;于是个人就觉得很奇怪&#xff0c;难道不应该只 catch 可能出问题的代码吗&#xff1f;同事告诉我说 try catch 太细的话会出现内外作用域不一致&#xff0c;需要提前声明变量。 let res: D…

【微服务】微服务保护Sentinel

微服务保护Sentinel1.初识Sentinel1.1.雪崩问题及解决方案1.1.1.雪崩问题1.1.2.超时处理1.1.3.仓壁模式1.1.4.断路器1.1.5.限流1.1.6.总结1.2.服务保护技术对比1.3.Sentinel介绍和安装1.3.1.初识Sentinel1.3.2.安装Sentinel1.4.微服务整合Sentinel2.流量控制2.1.簇点链路2.1.快…

豆瓣引流流程

豆瓣引流注册账号养号如何把豆瓣的帖子打造好并且引流到微信注册账号 第一&#xff1a;可以去营业厅或者卡商那里购买一批卡来进行注册。 第二&#xff1a;可以通过接码平台进行大量的一个小号注册&#xff0c;我们注册的号前期是作为一个顶帖号来使用。 第三&#xff1a;我…

商业智能 BI 跟业务系统的思维差异

我们在跟企业的沟通过程中经常发现&#xff0c;很多企业还是分不清商业智能 BI 跟一般的业务信息化系统定位、用户、思维层面上的差异。因为在企业的IT信息化规划中&#xff0c;基础的业务系统建设一定是走在前面的&#xff0c;有了这些系统基础&#xff0c;才会有数据的积累&a…

Python绘制图片一

文章目录一、代码段讲解1. theta np.linspace(0.0, 2 * np.pi, N , endpointFalse)2. ax plt.subplot(111,projectionpolar)3. bar.set_facecolor(plt.cm.viridis(r / 10.))4. bar.set_alpha(0.5)二、附录一、代码段讲解 1. theta np.linspace(0.0, 2 * np.pi, N , endpoint…

Windows软件:如何使用VMware® Workstation 16 Pro安装Centos7操作系统

前言&#xff1a; 在我们开发Java项目当中&#xff0c;经常会将jar包部署在Linux操作系统中运行&#xff0c;其中Centos7使用最广泛&#xff0c;前后端的各种运行环境所必须的软件均在此上运行&#xff0c;本章我们就来讲一下如何使用VMware安装Centos7系统&#xff0c;以便我们…

08技术太卷我学APEX-页面上显示静态图片

08技术太卷我学APEX-页面上显示静态图片 0 我想在首页面上留个人微信二维码和微信群二维码 我想在《技术太卷我学APEX》首页上留下联系方式&#xff0c;方便同学们加群一起交流联系方式。 先手机登录个人微信&#xff0c;截图个人微信二维码和《技术太卷我学APEX》微信群二维…

【MyBatis持久层框架】MyBatis参数传递详细解读

文章目录1. 前言2. MyBatis 参数传递3. 多个参数4. 单个参数4.1 POJO类4.2 Map集合类4.3 Collection集合类型4.4 List集合类型4.5 Array类型4.6 其他类型5. 总结1. 前言 前面在使用配置文件实现增删改查一文中&#xff0c;我们说到&#xff0c;使用 MyBatis 的 Mapper 代理开发…

glibc memcpy内部机制学习记录

判断需要拷贝的字节数是否大于临界值&#xff08;16或8&#xff09;。如果小于&#xff0c;直接按照one byte by one byte来拷贝。如果大于&#xff1a; 1、先进行内存对齐。假设要拷贝的目的地址如下所示 其中start为拷贝目的地的起始地址 &#xff0c;end为拷贝目的地的结束…

企业的内部文档太杂乱,有什么好用的文档管理软件?

企业内部文档的管理&#xff0c;是一个老生常谈的问题。 有些企业的文档管理比较混乱&#xff0c;很难做好企业内部的信息管控。 我们可以先从以下几个方面入手&#xff1a; 企业内部文档杂乱分散&#xff0c;集中式的管理&#xff1b;信息更新不及时、错误频繁&#xff0c;通过…

大数据NiFi(十六):处理器Connection连接

文章目录 处理器Connection连接 一、查看队列中的FlowFile 二、查看FlowFile自定义属性值

【数据结构初阶】第一节.初识时间和空间复杂度

文章目录 前言 一、认识数据结构 二、时间复杂度 2.1 时间复杂度的概念 2.2 计算时间复杂度 2.2.1 大O的渐进表示法 2.3 常见时间复杂度计算举例 三、空间复杂度 3.1 空间复杂度的概念 3.2 计算空间复杂度 3.3 常见空间复杂度计算举例 四、常见复杂度的对比&#xff1…

CVE-2022-26937 Windows NFS 栈溢出漏洞分析

简介 NFS全称Network File System&#xff0c;即网络文件系统&#xff0c;用于服务器和客户机之间文件访问和共享的通信&#xff0c;从而使客户机远程访问保存在存储设备上的数据。 CVE-2022-26937是微软5月份修复的Windows NFS中一个对NLM响应处理不当的栈溢出漏洞&#xff…

OAuth2(1)

目录 一、什么是OAuth2.0 二、OAuth2中的角色 三、认证流程 四、生活中的OAuth2思维 五、令牌的特点 六、OAuth2授权方式 1.授权码 2.隐藏方式 3.密码方式 4.凭证方式 一、什么是OAuth2.0 OAuth2.0是目前使用非常广泛的授权机制&#xff0c;用户授权第三方应用…

红宝书学习

第一章 认识js js的组成部分有哪些&#xff1f; ①ecma 核心语法 api ②dom 提供与网页内容交互的方法和接口 ③bom 浏览器对象模型&#xff0c;提供了和浏览器交互的接口 use strict 是什么&#xff1f; use strict 是一种 ECMAscript5 添加的&#xff08;严格模式&#xff…

玩了半年NFT,一心进军Web3的Prada到底要怎么玩?

图片来源&#xff1a;无界AI绘画工具生成2022年1月&#xff0c;奢侈品品牌Prada与阿迪达斯玩了一把“联合营销”&#xff0c;玩法是这样的&#xff1a;首先&#xff0c;两个品牌邀请粉丝上传个人照片&#xff0c;然后&#xff0c;品牌抽取3000名粉丝的作品&#xff0c;交由数字…

【Rust】12. 自动化测试

12.1 编写测试 12.1.1 测试函数 测试函数&#xff1a;在一个函数前加上一行 #[test] 注解将普通函数变成测试函数 12.1.2 assert! 宏 12.1.3 assert_eq! 与 assert_ne! assert_eq!(left, right) 与 assert_eq!(left, right) 在失败时会返回 left 与 right 两个值&#xff0c…