SSM框架,MyBatis框架的学习(上)

MyBatis简介

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

持久层框架对比

  • JDBC
    • SQL 夹杂在Java代码中耦合度高,导致硬编码内伤
    • 维护不易且实际开发需求中 SQL 有变化,频繁修改的情况多见
    • 代码冗长,开发效率低
  • Hibernate 和 JPA
    • 操作简便,开发效率高
    • 程序中的长难复杂 SQL 需要绕过框架
    • 内部自动生成的 SQL,不容易做特殊优化
    • 基于全映射的全自动框架,大量字段的 POJO 进行部分映射时比较困难。
    • 反射操作太多,导致数据库性能下降
  • MyBatis
    • 轻量级,性能出色
    • SQL 和 Java 编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据
    • 开发效率稍逊于 Hibernate,但是完全能够接收

开发效率:Hibernate>Mybatis>JDBC

运行效率:JDBC>Mybatis>Hibernate

MyBatis 框架下,SQL语句编写位置发生改变,从原来的Java类,改成XML或者注解定义

推荐在XML文件中编写SQL语句,让用户能更专注于 SQL 代码,不用关注其他的JDBC代码。

Mybatis 中的 Mapper 接口相当于以前的 Dao。但是区别在于,Mapper 仅仅只是建接口即可,我们不需要提供实现类,具体的SQL写到对应的Mapper文件

MyBatis案例:

Employee类:

package com.ergou.pojo;public class Employee {private Integer empId;private String empName;private Double empSalary;//getter | setterpublic Integer getEmpId() {return empId;}public void setEmpId(Integer empId) {this.empId = empId;}public String getEmpName() {return empName;}public void setEmpName(String empName) {this.empName = empName;}public Double getEmpSalary() {return empSalary;}public void setEmpSalary(Double empSalary) {this.empSalary = empSalary;}
}

Mapper接口:

package com.ergou.mapper;import com.ergou.pojo.Employee;public interface EmployeeMapper {
//根据id查询员工信息
Employee queryById(Integer id);
//根据id删除员工
int deleteById(Integer id);
}

EmployeeMapper.xml:(sql语句写在其中)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""<https://mybatis.org/dtd/mybatis-3-mapper.dtd>">
<!-- namespace等于mapper接口类的全限定名,这样实现对应-->
<!--xml方式写sql语句
mybatis固定在特定的标签内写sql语句
mapper的xml文件要有约束-->
<mapper namespace="com.ergou.mapper.EmployeeMapper"><!--查询使用 select标签id =方法名resultType =返回值类型标签内编写SQL语句mapper接口下不能方法重载,否则全限定符对应不到唯一的方法
-->
<select id="queryById" resultType="com.ergou.pojo.Employee">
<!-- #{empId}代表动态传入的参数,并且进行赋值!后面详细讲解-->
SELECT emp_id empId,emp_name empName, emp_salary empSalaryFROM t_empWHERE emp_id = #{empId}</select><delete id="deleteById">DELETE FROM t_emp WHERE emp_id = #{id}</delete>
</mapper>

mybatis-config.xml:(配置mybatis框架)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""<http://mybatis.org/dtd/mybatis-3-config.dtd>">
<configuration><!-- environments表示配置Mybatis的开发环境,可以配置多个环境,在众多具体环境中,使用default属性指定实际运行时使用的环境。default属性的取值是environment标签的id属性的值。-->
<environments default="development">
<!-- environment表示配置Mybatis的一个具体的环境-->
<environment id="development">
<!-- Mybatis的内置的事务管理器-->
<transactionManager type="JDBC"/>
<!--配置数据源-->
<dataSource type="POOLED">
<!--建立数据库连接的具体信息-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis-example"/><property name="username" value="liergou"/><property name="password" value="liergou070509"/></dataSource></environment></environments><mappers>
<!-- Mapper注册:指定Mybatis映射文件的具体位置--><!-- mapper标签:配置一个具体的Mapper映射文件--><!-- resource属性:指定Mapper映射文件的实际存储位置,这里需要使用一个以类路径根目录为基准的相对路径--><!--对Maven工程的目录结构来说,resources目录下的内容会直接放入类路径,所以这里我们可以以resources目录为基准-->
<mapper resource="mappers/EmployeeMapper.xml"/></mappers></configuration>

测试:

@Test
public void test_01() throws IOException {
//1.读取外部配置文件
InputStream ips = Resources.getResourceAsStream("mybatis-config.xml");
//2.创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(ips);
//3.根据sqlSessionFactory创建sqlSession(每次业务创建一个,用完就释放)
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.获取接口的代理对象
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
//调用方法
Employee employee = mapper.queryById(1);System.out.println(employee);
//5.提交事务(非DQL)和释放资源
sqlSession.commit();sqlSession.close();
}

ibatis方式和原理

mybatis进行数据库的crud是对ibatis的封装和优化

ibatis方式进行数据库操作

  1. 不要求写对应的mapper接口
  2. 直接创建mapper.xml文件,在内部编写xml文件
  3. namespace属性没有要求,随便写一个字符串
  4. 内部通过crud标签声明对应的sql语句即可

StudentMapper.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""<https://mybatis.org/dtd/mybatis-3-mapper.dtd>">
<!--namespace:mapper对应接口的全限定符-->
<!--ibatis方式进行数据库操作1.不要求写对应的mapper接口2.直接创建mapper.xml文件,在内部编写xml文件3.namespace属性没有要求,随便写一个字符串-->
<mapper namespace="StudentMapper"><select id="query" resultType="com.ergou.pojo.Student">SELECT * FROM student WHERE sid = #{id}</select>
</mapper>

在对应的config.xml文件中的mapper标签中配置StudentMapper.xml

<mappers>
<!-- Mapper注册:指定Mybatis映射文件的具体位置--><!-- mapper标签:配置一个具体的Mapper映射文件--><!-- resource属性:指定Mapper映射文件的实际存储位置,这里需要使用一个以类路径根目录为基准的相对路径--><!--对Maven工程的目录结构来说,resources目录下的内容会直接放入类路径,所以这里我们可以以resources目录为基准-->
<mapper resource="mappers/EmployeeMapper.xml"/><mapper resource="mappers/StudentMapper.xml"/>
</mappers>

测试:

@Test
public void test_02() throws IOException {
//1.读取外部配置文件
InputStream ips = Resources.getResourceAsStream("mybatis-config.xml");
//2.创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(ips);
//3.根据sqlSessionFactory创建sqlSession(每次业务创建一个,用完就释放)
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.直接sqlSession提供的crud方法进行数据库查询即可
//方法名为:select / insert / delete / update//selectOne和selectList方法:参数1为sql标签对应的id值,参数二为执行sql语句传入的参数
Student student = sqlSession.selectOne("StudentMapper.query", 1);System.out.println(student);
//5.提交事务(非DQL)和释放资源
sqlSession.commit();sqlSession.close();
}

缺点:其中的selectOne和selectList方法只能传一个参数

而在mybatis中,可以自定义相应的sql语句和相应的方法

mybatis基本使用

向sql语句传参

#{}

#{}是作为占位符给指定目标赋值,当值传入占位符时,就会给指定目标传入此值

${}

${}是作为拼接块,将传入的值以字符串的形式拼接在sql语句后

建议使用#{},防止外界sql注入而改变sql语句原本的意思

${}在动态的列名、表名、关键字等处使用

//注解方式传入参数!!
@Select("select * from user where ${column} = #{value}")
User findByColumn(@Param("column") String column,@Param("value") String value);

数据输入

简单类型

这里的简单类型指的是单值的类型的变量,比如基本数据类型和字符串类型,一个变量中只有一个数据值。

<!--若传入的是单个简单类型值,#{}中间的名字随便写,因为传入的值为单个值的数据,不存在需要辨别-->
<delete id="deleteById">DELETE FROM t_emp WHERE emp_id = #{id}
</delete>

单个实体对象传入

若传入的是单个实体对象:#{}中间的名字要与要传入的值的的属性名一致,以方便对应赋值

<!--若传入的是单个实体对象,#{}中间的名字要与要传入的值的的属性名一致,以方便对应赋值-->
<insert id="insertEmployee">INSERT INTO t_emp(emp_name,emp_salary)VALUES(#{empName},#{empSalary})
</insert>

多个简单类型传入

方式①:使用注解@Param指定多个简单参数的key(在#{}中使用的名称)

//根据员工姓名和工资查询员工信息
List<Employee> queryByNameAndSalary(@Param("a") String name,@Param("b") Double salary);
<!--若传入的是多个简单类型的值-->
<select id="queryByNameAndSalary" resultType="com.ergou.pojo.Employee">SELECT emp_id empId,emp_name empName,emp_salary empSalaryFROM t_empWHERE emp_name = #{a} AND emp_salary = #{b}
</select>

方案②:mybatis默认机制,使用默认的名字arg0,arg1,……(形参列表中每个参数的key名字默认为arg0,arg1,arg2,以此类推(以0开头)),或使用param1,param2,……(默认以1开头)

Map类型参数传入

若传入的是Map类型的数据,#{}中直接写Map集合中要传入的value值对应的key值即可

<!--若传入的是Map类型的数据,#{}中直接写Map集合中要传入的value值对应的key值即可-->
<insert id="insertEmployeeMap">INSERT INTO t_emp(emp_name,emp_salary)VALUES(#{name},#{salary})
</insert>

数据输出

数据输出总体上有两种形式:                 

  • 增删改操作返回的受影响行数:直接使用 int 或 long 类型接收即可
  • 查询操作的查询结果

单个简单类型

若是DML语句,返回受影响行数,则不需要手动指定返回值类型

<!--若是DML语句,返回受影响行数,则不需要手动指定返回值类型-->
<delete id="deleteById">DELETE FROM t_emp WHERE emp_id = #{id}
</delete>

若是查询语句,需要指定输出类型,使用resultType属性值,在相应的select标签中指定返回值类型

resultType属性值的语法:

①类的全限定符

②别名的简称

别名映射的类型
_bytebyte
_char (since 3.5.10)char
_character (since 3.5.10)char
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
char (since 3.5.10)Character
character (since 3.5.10)Character
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
bigintegerBigInteger
objectObject
object[]Object[]
mapMap
hashmapHashMap
listList
arraylistArrayList
collectionCollection

如果类没有别名,则需要使用全限定符或自定义别名

自定义别名方法:(typeAliases标签写在settings标签下)

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:

<typeAliases><typeAlias alias="Author" type="domain.blog.Author"/><typeAlias alias="Blog" type="domain.blog.Blog"/>
</typeAliases>

当这样配置时,Blog 可以用在任何使用 domain.blog.Blog 的地方。

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:

<typeAliases> <package name="domain.blog"/> </typeAliases>

每一个在包 domain.blog 中的 Java Bean,在没有@Alias注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author若有@Alias注解,则别名为其注解指定的值。见下面的例子:

@Alias("author")
public class Author {...
}

单个实体类型

<!--返回单个自定义实体类型-->
<select id="queryById" resultType="com.ergou.pojo.Employee">SELECT emp_id empId,emp_name empName,emp_salary empSalaryFROM t_emp WHERE emp_id = ${id}</select>

默认要求:返回单个实体类型时,列名和属性名要对应且一致,才能进行实体类的属性映射

也可以进行设置(在mybatis-config.xml文件中进行),设置支持驼峰式自动映射,即自动将下划线格式转化为驼峰格式,例:将emp_id转化为empId

<!-- 在全局范围内对Mybatis进行配置 -->
<settings><!-- 具体配置 --><!-- 从org.apache.ibatis.session.Configuration类中可以查看能使用的配置项 --><!-- 将mapUnderscoreToCamelCase属性配置为true,表示开启自动映射驼峰式命名规则 --><!-- 规则要求数据库表字段命名方式:单词_单词 --><!-- 规则要求Java实体类属性名命名方式:首字母小写的驼峰式命名 --><setting name="mapUnderscoreToCamelCase" value="true"/></settings>

Map类型

适用于SQL查询返回的各个字段综合起来并不和任何一个现有的实体类对应,没法封装到实体类对象中。能够封装成实体类类型的,就不使用Map类型。

<!-- Map<String,Object> selectEmpNameAndMaxSalary(); -->
<!-- 返回工资最高的员工的姓名和他的工资 -->
<select id="selectEmpNameAndMaxSalary" resultType="map">SELECTemp_name 员工姓名,emp_salary 员工工资,(SELECT AVG(emp_salary) FROM t_emp) 部门平均工资FROM t_emp WHERE emp_salary=(SELECT MAX(emp_salary) FROM t_emp)
</select>

List类型

若返回值是集合,resultType不需要指定集合类型,只需要指定泛型即可

<!-- List<Employee> selectAll(); -->
<select id="selectAll" resultType="com.atguigu.mybatis.entity.Employee">select emp_id empId,emp_name empName,emp_salary empSalaryfrom t_emp
</select>

关于主键

自增长主键回显:(由mysql的auto_increment自动产生的主键值)

使用userGeneratedKeys属性,将其设置为true

在keyColumn属性中写上主键的列名(可省略)

在keyProperty属性中指定存储主键的属性名

最终生成的对象会多一个其属性名为keyProperty指定的属性名的属性,里面存储着插入对象的的主键值

<!-- int insertEmployee(Employee employee); -->
<!-- useGeneratedKeys属性字面意思就是“使用生成的主键” -->
<!-- keyProperty属性可以指定主键在实体类对象中对应的属性名,Mybatis会将拿到的主键值存入这个属性 -->
<insert id="insertEmployee" useGeneratedKeys="true" keyProperty="empId">insert into t_emp(emp_name,emp_salary)values(#{empName},#{empSalary})
</insert>

非自增长类型主键的维护:(不是自动增长的主键值)

在insert标签中使用selectKey标签,在其中写一段sql语句(查询),关于select标签:

属性:

  • order:sql语句是在插入语句之前还是之后进行
  • resultType:返回值类型
  • keyProperty:查询结果给哪个属性赋值,这个属性可以给insert标签中的sql语句使用同时在生成的相应java对象中也会多一个此属性,可以通过get方法获取

实体类属性和数据库字段对应关系

当列名和属性名不一致,有以下解决方案:

①给查询的列名起别名,此别名和属性名一致

②使用驼峰式映射

<!-- 使用settings对Mybatis全局进行设置 -->
<settings><!-- 将xxx_xxx这样的列名自动映射到xxXxx这样驼峰式命名的属性名 --><setting name="mapUnderscoreToCamelCase" value="true"/></settings>

③resultMap自定义映射

resultType按照规则自动映射:按照是否开启驼峰式映射,自己映射属性和列名,只能映射一层结构(即一个对象的属性是其他类的对象,该属性的属性不会自动映射)

resultMap自定义映射:使用resultMap标签,result标签就是一个中间处理的标签,处理数据库的列名和属性名之间的映射

<!-- 专门声明一个resultMap设定column到property之间的对应关系 -->
<!--属性:id:供select标签的selectMap属性调用的值-->
<resultMap id="selectEmployeeByRMResultMap" type="com.atguigu.mybatis.entity.Employee"><!-- 使用id标签设置主键列和主键属性之间的对应关系 --><!-- column属性用于指定字段名;property属性用于指定Java实体类属性名 --><id column="emp_id" property="empId"/><!-- 使用result标签设置普通字段和Java实体类属性之间的关系 --><result column="emp_name" property="empName"/><result column="emp_salary" property="empSalary"/></resultMap><!-- Employee selectEmployeeByRM(Integer empId); 
属性改为使用resultMap属性-->
<select id="selectEmployeeByRM" resultMap="selectEmployeeByRMResultMap">select emp_id,emp_name,emp_salary from t_emp where emp_id=#{empId}</select>

select标签中调用了result标签,result标签中的type属性指定了返回值类型,间接指定了select标签的返回值类型

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

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

相关文章

28. 找出字符串中第一个匹配项的下标(力扣LeetCode)

文章目录 28. 找出字符串中第一个匹配项的下标题目描述暴力KMP算法 28. 找出字符串中第一个匹配项的下标 题目描述 给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。…

mapbox高德地图与相机

mapbox高德地图与相机 本案例使用Mapbox GL JavaScript库创建高德地图。 演示效果引入 CDN 链接地图显示 创建地图实例定义地图数据源配置地图图层 设置地图样式实现代码 1. 演示效果 2. 引入 CDN 链接 <script src"https://api.mapbox.com/mapbox-gl-js/v2.12.0/mapb…

Android虚拟机Dalvik和ART

前言&#xff1a;Android虚拟机包括Dalvik和ART&#xff0c;它们是用于在Android设备上运行应用程序的关键组件。 Dalvik虚拟机&#xff1a; 1. 设计目的&#xff1a; Dalvik虚拟机是在Android早期版本中使用的虚拟机&#xff0c;其设计目的是为了在资源受限的移动设备上执…

项目实战:Qt监测操作系统cpu温度v1.1.0(支持windows、linux、国产麒麟系统)

若该文为原创文章&#xff0c;转载请注明出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/136277231 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结…

全面升级!Apache HugeGraph 1.2.0版本发布

图数据库以独特的数据管理和分析能力&#xff0c;在企业数智化转型的过程中正在成为数据治理的核心&#xff0c;根据IDC调研显示&#xff0c;95%的企业认为图数据库是重要的数据管理工具&#xff0c;超过65%的厂商认为在业务上图数据库优于其他选择&#xff0c;尤其是在金融风控…

Linux设备模型(四) - uevent应用:内核发送uevent,用户空间接收uevent

1&#xff0c;内核发送uevent 内核发送uevent的API由lib/kobject_event.c文件实现&#xff0c;include/linux/kobject.h是头文件。 enum kobject_action {KOBJ_ADD,KOBJ_REMOVE,KOBJ_CHANGE,KOBJ_MOVE,KOBJ_ONLINE,KOBJ_OFFLINE,KOBJ_MAX };/* kobject_uevent不能用在中断上下…

2024年2月19日-2月25日(全面进行+收集免费虚幻商城资源,20小时,合计2561小时,剩余7439小时)

试试周一到周五重点进行&#xff0c;周末抄写源码&#xff0c;周一晚上看书很快就在22&#xff1a;00睡着&#xff0c;早上可以看看视频教程&#xff0c;出租车上补觉。 执行如下&#xff1a; 周一&#xff1a; 8&#xff1a;01-9&#xff1a;20ue4 rpg&#xff08;184&#xf…

Unity零基础到进阶 | Unity中的 RectTransformUtility 方法整理汇总

Unity零基础到进阶 ☀️| RectTransformUtility 方法整理汇总一、RectTransformUtility 官方文档1.1 RectTransformUtility.CalculateRelativeRectTransformBounds&#xff08;重&#xff09;1.2 RectTransformUtility.FlipLayoutAxes1.3 RectTransformUtility.FlipLayoutOnAxi…

观察者模式与发布订阅模式

观察者模式 定义&#xff1a; 观察者模式是一种行为型设计模式&#xff0c;定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。 结构图&#xff1a; ES6简易代码实现&#xff1a; //ts环境下…

Nginx——安装和反向代理

Nginx安装与应用 1.1 Nginx介绍 Nginx 是一个高性能的HTTP和反向代理服务器,特点是占有内存少&#xff0c;并发能力强 Nginx可以作为静态页面的web服务器&#xff0c;同时还支持CGI协议的动态语言&#xff0c;比如perl、php等。但是不支持java。Java程序只能通过与tomcat配合…

谷歌AI发展史:从阿尔法围棋到Gemini与Gemma的开源创新

谷歌一直是人工智能领域的重要推动者。本文将回顾谷歌AI的发展历程&#xff0c;从阿尔法围棋到现如今的Gemini和Gemma&#xff0c;探讨谷歌在人工智能领域的重大突破和创新。 1. 引言 在计算机科学领域&#xff0c;谷歌一直是人工智能&#xff08;AI&#xff0…

华为OD机试真题-数的分解-2023年OD统一考试(C卷)--Python3-开源

参考链接&#xff1a; 华为OD机试真题-用连续自然数之和来表达整数-2023年OD统一考试&#xff08;C卷&#xff09;—python代码免费

MasterAlign全景视觉点胶应用软件说明书

MasterAlign视觉软件通过高精度的图像处理和机器学习算法&#xff0c;实现了对点胶过程的全面控制和管理。以下是关于MasterAlign在全景视觉点胶应用场景中如何使用的详细说明。看完全文相信一定能让您快速上手使用。

刷题第1天:leetcode704--数组元素查找--二分法查找算法

第一部分---数组的基础知识介绍&#xff1a; 1.数组的定义&#xff1a;数组是存放在连续内存空间上的相同数据类型的数据的集合&#xff1b; 2.数组可以通过下标索引的方式获取到下标对应的数据&#xff1b; 3.数组下标是从0开始的&#xff0c;数组的内存空间地址是连续的&a…

多维时序 | Matlab实现CPO-BiTCN-BiGRU冠豪猪优化时间卷积神经网络双向门控循环单元多变量时间序列预测模型

多维时序 | Matlab实现CPO-BiTCN-BiGRU冠豪猪优化时间卷积神经网络双向门控循环单元多变量时间序列预测模型 目录 多维时序 | Matlab实现CPO-BiTCN-BiGRU冠豪猪优化时间卷积神经网络双向门控循环单元多变量时间序列预测模型预测效果基本介绍程序设计参考资料 预测效果 基本介绍…

基于R语言的Meta分析【全流程、不确定性分析】方法与Meta机器学习技术应用

Meta分析是针对某一科研问题&#xff0c;根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法&#xff0c;对来源不同的研究成果进行收集、合并及定量统计分析的方法&#xff0c;最早出现于“循证医学”&#xff0c;现已广泛应用于农林生态&#xff0c;资源环境等方面。…

适配器模式(Adapter Pattern)

定义 适配器模式是一种结构型设计模式&#xff0c;它允许将一个类的接口转换成客户希望的另一个接口。这种模式通常用于解决接口不兼容的问题。适配器模式包括三个角色&#xff1a;目标接口&#xff08;Target&#xff09;、适配器&#xff08;Adapter&#xff09;和被适配者&…

设计模式(六)代理模式

相关文章设计模式系列 1.代理模式简介 代理模式介绍 代理模式也叫委托模式&#xff0c;是结构型设计模式的一种。在现实生活中我们用到类似代理模式的场景有很多&#xff0c;比如代购、代理上网、打官司等。 定义 为其他对象提供一种代理以控制这个对象的访问。 代理模式…

【Elasticsearch专栏 18】深入探索:Elasticsearch核心配置与性能调优 保姆级教程 企业级实战

文章目录 导言01 内存设置优化1.1 JVM堆内存设置1.2 禁用Swap分区1.3 线程栈内存设置 02 文件描述符限制优化2.1 查看当前的文件描述符限制2.2 临时更改文件描述符限制2.3 永久更改文件描述符限制2.4 Elasticsearch文件描述符配置2.5 验证更改 03 网络和I/O优化3.1 网络优化3.2…

Layer1 明星项目 Partisia Blockchain 何以打造互操作、可创新的数字经济网络

我们的目标是创建一个以用户为中心的全新数字经济网络&#xff1a;在去信任化和公平透明的环境下&#xff0c;所有的隐私数据都能够得到天然保障&#xff0c;企业、用户等各角色的协作与共享将会更顺利地进行。 —— Partisia Blockchain 团队 作为一个以 Web3 安全为技术方向的…