MyBatis处理SQL语句映射

基础MyBatis问题以去看MyBatis基础。

使用log4j设置日志在控制台打印SQL语句及其执行信息

也可以使用MyBatis基础中用的slf4j。

在pom.xml文件中引入log4j坐标依赖

<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.12</version>
</dependency>

在resourecs目录下设置log4j.properties文件配置信息用于在控制台查看SQL语句的执行和拼接情况

log4j.rootLogger = INFO,CONSOLE,FILElog4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayoutlog4j.appender.CONSOLE.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%nlog4j.appender.FILE=org.apache.log4j.DailyRollingFileAppenderlog4j.appender.FILE.DatePattern='.'yyyy-MM-dd
log4j.appender.FILE.File=D:/logs/mybatis.log
log4j.appender.FILE.layout = org.apache.log4j.PatternLayoutlog4j.appender.FILE.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p]- %m%n

然后在MyBatis核心配置文件配置,如下:

MyBatis核心配置文件配置半自动映射和全自动映射

<!--mybatis全局配置-->
<settings><!-- 如果使用log4j打印SQL语句,则需要配置 value 的值 --><!-- value="STDOUT_LOGGING" 使用日志打印SQL语句(会在控制台自动打印执行的SQL语句)--><setting name="logImpl" value="STDOUT_LOGGING"/><!-- value="LOG4J" 不打印SQL语句,只打印日志信息-->
<!--        <setting name="logImpl" value="LOG4J"/>--><!--默认情况下,MyBatis 会自动进行结果映射,即把数据库查询结果映射为 Java Bean。但是,如果数据库字段与 Java Bean 的属性名不一致,则需要设置自动映射为NONE,即不进行自动映射,此时需要手动进行映射。默认:半自动映射(封装),即自动把sql配置xml文件中select查询出来的数据封装成resultType或resultMap指定的JavaBean对象,如果封装了多个对象,则自动变成List集合返回。NONE:关闭自动映射(封装),关闭后,需要使用resultMap进行手动映射。FULL:完全自动映射(嵌套封装,一对一、一对多,对象套对象)-->
<!--        <setting name="autoMappingBehavior" value="NONE"/>--><setting name="autoMappingBehavior" value="FULL"/>
</settings>

一、查

resultType:返回值类型,会自动把查出来的数据自动封装成该类型对象并返回,如果有多个,则会把封装的对象放到一个list集合中并返回。

自动封装时会按查询的数据库表的字段先后顺序让该数据库表的字段名与要封装成的对象的属性名进行匹配,若匹配上则会把该数据封装到对象中。(尤其是两张有相同字段名表联合查询,并且MyBatis进行自动封装时,会出现该字段的数据封装错误的问题,可见 1.6一对一 )。

1.1 #{} 和 ${}

dao层接口方法

public Provider findProviderById(Integer id);

SQL映射

  • #{}是将参数数据以占位符的形式与SQL语句进行拼接,防止SQL注入攻击。
  • ${}是将参数数据以原样输出的形式与SQL语句进行拼接,但是不建议使用,容易出现SQL注入问题。
  • {}中的参数名要与接口方法中的参数名一致
  • sql语句最后的分号可不写。

(可以看日志在控制台输出执行的所拼接的sql语句,见Mybatis基础)

<!--id要与接口中方法名一致-->
<!--parameterType:参数类型  可不写-->
<!--resultType:返回值类型,会把查出来的数据封装成该类型对象并返回,如果有多个,则会把封装的对象放到一个list集合中并返回-->
<!--sql语句最后的分号可不写-->
<select id="findProviderById" resultMap="ProviderMap"><!--#{}是将参数数据以占位符的形式与SQL语句进行拼接,防止SQL注入攻击${}是将参数数据以原样输出的形式与SQL语句进行拼接,但是不建议使用,容易出现SQL注入问题-->select id,proCode,proName,proDesc from smbms_provider a where a.id=#{id}
</select>

1.2 特殊字符处理

特殊字符(比如>、<等特殊符号)处理,这里以查询id小于指定id的SQL语句为例:

  1. 转义字符:如<会被认为是一个标签的开始,需要转义为&lt;,一般用于少量使用特殊字符的SQL语句(>转义对应&gt;,>能正常使用,可以不用转义)。
  2. CDATA区(当作纯文本处理):写CD会有提示,如在里面写<号 <![CDATA[ < ]]>,一般用于大量使用特殊字符的SQL语句。
<select id="selectById" resultMap="brandResultMap"><!--使用转义-->select * from tb_brand where id &lt;= #{id};<!--使用CDATA区-->select * from tb_brand where id <![CDATA[ < ]]> #{id};
</select>

1.3 模糊查询不能用单引号

注意:这里模糊查询不能写单引号,如:‘%${proName}%’,这样写会报错。要用concat拼接,concat(‘%’,#{pname},‘%’)。

<select id="findList" resultType="Provider">select id,proCode,proName,proDescfrom smbms_provider awhere proName like concat('%',#{pname},'%')and proDesc like concat('%',#{pdesc},'%')
</select>

1.4 自动封装数据问题

如果数据库表的字段名称(列名)和resultType指定的实体类的属性名称不一样,则不能自动封装数据(即若对应不上则封装后数据为null)。

有以下三个方案可以解决:

1.4.1 起别名

给与实体类中属性名不一样的列名起别名,这个别名要与对应的实体类中的属性名一致。
缺点:每次查询都要定义一次别名。

<select id="selectAll" resultType="brand"><!--brand_name是列名,要起别名与Brand类中属性brandName的属性名一致,否则无法封装-->select id, brand_name as brandName, company_name as companyName, ordered, description, status from tb_brand;
</select>

1.4.2 resultMap(最常用)

数据库字段与要封装成的实体类属性不一致才需要字段映射。

如果关闭了自动映射,则只能通过resultMap封装(映射)指定的数据

  1. 定义<resultMap>标签:
    • type:要封装成的数据类型
    • <id property="id" column="id"/>用来完成主键字段的映射。
    • <result property="brandName" column="brand_name"/>用来完成一般字段的映射,也能用于完成主键字段的映射(它俩只是为了区分字段,实际上没区别)。
      • property:实体类的属性名。
      • column:数据库表的字段名(列名)。
      • 若property和column的值一样,则可以不写这个字段映射。
      • jdbcType:数据库字段类型。
      • javaType:java字段类型。
      • jdbcType与javaType(可不写):告诉mybatis如何将数据库字段映射到java字段中,只是为了比较数据类型是否一致,一般都是写jdbcType=“VARCHAR” javaType=“String”。
  2. <select>标签中,使用resultMap属性替换resultType属性,并设置为对应resultMap的id。
<resultMap id="brandResultMap" type="brand"><!--数据库字段与实体类属性不一致才需要字段映射--><!--id用来完成主键字段的映射,如下。若数据库字段名与实体类属性名一致,可以不用写--><!--<id property="id" column="id"/>--><!--result用来完成一般字段的映射--><result property="brandName" column="brand_name" jdbcType="VARCHAR" javaType="String"/><result property="companyName" column="company_name"/>
</resultMap>
<select id="selectById" resultMap="brandResultMap">select * from tb_brand where id=#{id};
</select>

1.4 动态SQL

1.4.1 where、if

动态SQL条件查询,如下案例
if:条件判断,满足条件才会拼接其中写的SQL。
test:判断条件(多个判断条件间要用英文 and 或 or 拼接,不能用&&和||)

问题:若第一个条件判断不成立,则该条件下的SQL不会拼接,导致后面拼接的SQL语句错误(原本的第二个条件变成了第一个条件,若该条件满足,则会以and开头,SQL语句错误)
解决:

  1. 恒等式(方法较笨):所有条件开头都加and,并且让 1=1 这个恒等式作为第一个条件。
  2. <where>标签(常用):
    • 替换where关键字,会自动把第一个条件中SQL开头的and去掉(如果and存在)。
    • 第一个条件中的SQL开头可不加and,后面的条件中的SQL必须以and开头。
    • 如果<where>标签中没有要拼接的条件内容,则执行SQL时不会添加where关键字。
<select id="selectByCondition" resultMap="brandResultMap">select *from tb_brand
<!--        where--><!-- 若参数status为null,则该条件不会拼接,导致后面拼接的SQL语句错误(原本的第二个条件变成了第一个条件,且以and开头,SQL语句错误)-->
<!--            <if test="status!=null">-->
<!--                status = #{status}-->
<!--            </if>-->
<!--              --><!--用恒等式-->
<!--            1 = 1-->
<!--            <if test="status!=null">-->
<!--                and status = #{status}-->
<!--            </if>-->
<!--            <if test="companyName!=null and companyName!=''">-->
<!--                and company_name like #{companyName}-->
<!--            </if>-->
<!--            <if test="brandName!=null and brandName!=''">-->
<!--                and brand_name like #{brandName}-->
<!--            </if>--><where><if test="status!=null">status = #{status}</if><if test="companyName!=null and companyName!=''">and company_name like #{companyName}</if><if test="brandName!=null and brandName!=''">and brand_name like #{brandName}</if></where></select>

1.4.2 choose、when、otherwise

相当于Java中的if、elseif。

<select id="selectByConditionSingle" resultMap="brandResultMap">select id, brand_name as brandName, company_name as companyName, ordered, description, statusfrom tb_brand
<!--        where-->
<!--        <choose>&lt;!&ndash;最多只会拼接其中一个条件,谁先满足就拼接哪个条件&ndash;&gt;-->
<!--            <when test="status!=null">-->
<!--                status = #{status}-->
<!--            </when>-->
<!--            <when test="companyName!=null and companyName!=''">-->
<!--                company_name like #{companyName}-->
<!--            </when>-->
<!--            <when test="brandName!=null and brandName!=''">-->
<!--                brand_name like #{brandName}-->
<!--            </when>-->
<!--            <otherwise>&lt;!&ndash;前面都不满足时执行,避免没有传值时报错&ndash;&gt;-->
<!--                1 = 1-->
<!--            </otherwise>-->
<!--        </choose>--><!--如果不想用<otherwise>,则可以用<where>把<choose>包裹住--><where><choose><!--最多只会拼接其中一个条件,谁先满足就拼接哪个条件--><when test="status!=null">status = #{status}</when><when test="companyName!=null and companyName!=''">company_name like #{companyName}</when><when test="brandName!=null and brandName!=''">brand_name like #{brandName}</when></choose></where>
</select>

1.5 SQL片段

用于把一些重复使用的SQL语句的片段抽取出来,需要用时就调用。

使用<sql>标签定义SQL片段,id:唯一标识,调用时需要。
在SQL语句中使用<include>标签,通过refid指定要调用的SQL片段。

<!--sql片段-->
<sql id="brand_column">id, brand_name as brandName, company_name as companyName, ordered, description, status
</sql>
<select id="selectAll" resultType="brand"><!--没使用sql片段--><!--select id, brand_name as brandName, company_name as companyName, ordered, description, status from tb_brand;--><!--使用sql片段--><!--使用include标签的refid属性调用sql片段-->select <include refid="brand_column"/> from tb_brand;
</select>

1.6 一对一(association、数据封装错误)

一个收获地址对应一个用户。
需要在Address类中添加一个User类的对象属性,用于存储用户信息,如:

private User u;//存储用户对象信息

dao层接口方法

public List<Address> findAddressAll();

SQL映射

<select id="findAddressAll" resultMap="AddressMap">selecta.id,a.contact,a.addressDesc,a.tel,a.userId,b.id,b.userNamefrom smbms_address aleft join smbms_user bon a.userId=b.id
</select>
<resultMap id="AddressMap" type="Address">
<!--        jdbcType:数据库字段类型-->
<!--        javaType:java字段类型-->
<!--        jdbcType与javaType的作用:告诉mybatis如何将数据库字段映射到java字段中,只是为了比较数据类型是否一致,可不写,一般都是写jdbcType="VARCHAR" javaType="String"--><id property="id" column="id"/><result property="contact" column="contact" jdbcType="VARCHAR" javaType="String"/><result property="addressDesc" column="addressDesc"/><result property="tel" column="tel"/><!-- 一对一 property:指定封装实体类对象的属性名 javaType:指定封装的java对象类型--><!--如果想使用全自动映射,则必须有一个空的association,但与其写一个空的association不如用半自动映射,另写一个resultMap并引进来,进行手动封装--><association property="u" javaType="User" resultMap="UserMap"><!--如果是半自动映射,若association里面不设置映射,则不会把这里面的数据封装--><!--<id property="userName" column="userName"/>--><!--自动封装时会按查询的数据库表的字段先后顺序让该数据库表的字段名与要封装成的对象的属性名进行匹配,因为先查的是smbms_address的表的id,且User类的id属性名与smbms_address表的id字段名一致,因此会先把address的id封装进user对象的id值,而不是封装后面查询的address_user的id,从而导致数据封装错误除非手动封装,如下,或者把user表的id字段改为user_id-->
<!--            <id property="id" column="userId"/>--></association>
</resultMap>
<resultMap id="UserMap" type="User"><id property="id" column="userId"/><id property="userName" column="userName"/>
</resultMap>

1.7 一对多(collection)

一个用户对应多个收获地址。
需要在User类中添加一个list集合属性,用于存储收获地址信息。如:

private List<Address> addressList;//存储收获地址信息

dao层接口方法

public User findUserById(Integer id);

SQL映射

<select id="findUserById" resultMap="UserMap">select a.id,a.userName,b.id as addrId,b.contact,b.addressDescfrom smbms_user aleft join smbms_address bon a.id = b.userIdwhere a.id = #{id};
</select>
<!--id:唯一标识 type:映射的类型,支持别名-->
<resultMap id="UserMap" type="User"><!--若property和column的值一样,则可以不写这个字段映射。--><!--<id property="id" column="id"/>--><!--<result property="userName" column="userName"/>--><!--一对多 addressList:(User类)属性集合的名称  ofType:要封装成的对象(Address类)--><!--理解:就是把查询出来的数据中列名(或别名)与Address类的属性名对应的每一行数据封装成一个Address对象放到User类的addressList集合属性中--><collection property="addressList" ofType="Address"><id property="id" column="addrId"/><result property="contact" column="contact"/><result property="addressDesc" column="addressDesc"/></collection>
</resultMap>

1.8 foreach

自动遍历传过来的集合、数组、Map的key所对应的集合或数组

<foreach>标签:
item:获取每次循环的对象值
collection:指定循环集合list、array、map的key
index作用:获取集合元素索引,可充当参数使用,如:#{index}

  • 迭代List集合或数组时:index表示当前元素在List集合或数组中的下标位置(从 0 开始)
  • 迭代Map集合时:index表示当前元素的键(key)

open:前缀
close:后缀
separator:指定集合元素之间的分隔符

准备的sql片段

<sql id="userCols">id,userCode,userName,birthday
</sql>

1.8.1 传入集合

dao层接口方法

public List<User> findUserList1(List<Integer> ids);

SQL映射

<select id="findUserList1" resultType="User">select<include refid="userCols"/>from smbms_userwhere id in<!--(1,2,3,4,5)--><foreach item="id" collection="list" index="index" open="(" close=")" separator=",">#{id}</foreach>
</select>

1.8.2 传入数组

dao层接口方法

public List<User> findUserList2(Integer[] ids);

SQL映射

<select id="findUserList2" resultType="User">select<include refid="userCols"/>from smbms_userwhere id in<foreach item="id" collection="array" index="index" open="(" close=")" separator=",">#{id}</foreach>
</select>

1.8.3 传入 map

dao层接口方法

public List<User> findUserList3(Map<String,Object> map);

SQL映射

<select id="findUserList3" resultType="User">select<include refid="userCols"/>from smbms_userwhere id in<!--这里ids是map的一个键,其值是一个数组--><foreach item="id" collection="ids" index="index" open="(" close=")" separator=",">#{id}</foreach>and userName = #{name}
</select>

二、增、删、改

增、删、改默认返回int,无法修改,不用写resultType,写了会报错。

2.1 增(使用trim实现动态SQL)

dao层接口方法

public int saveUser(User user);

SQL映射

<trim>标签:

  • prefix:给sql语句拼接的前缀。
  • suffix:给sql语句拼接的后缀。
  • prefixOverrides:自动去除sql语句前面的关键字或者字符(如果存在),该关键字或者字符由prefixOverrides属性指定,假设该属性指定为"AND",当sql语句的开头为"AND",trim标签将会去除该"AND"。
  • suffixOverrides:自动去除sql语句前面的关键字或者字符(如果存在),该关键字或者字符由prefixOverrides属性指定。
<insert id="saveUser"><!--为了实现动态SQL,可以使用trim标签-->insert into smbms_user<trim prefix="(" suffixOverrides="," suffix=")"><if test="userCode!=null">userCode,</if><if test="userName!=null">userName,</if><if test="userPassword!=null">userPassword,</if><if test="gender!=null">gender,</if><if test="birthday!=null">birthday,</if></trim>values<trim prefix="(" suffixOverrides="," suffix=")"><if test="userCode!=null">#{userCode},</if><if test="userName!=null">#{userName},</if><if test="userPassword!=null">#{userPassword},</if><if test="gender!=null">#{gender},</if><if test="birthday!=null">#{birthday},</if></trim>
</insert>

2.2 改(set标签)

dao层接口方法

public int updateUser(User user);

SQL映射

直接使用set关键字会导致最后拼接SQL时要修改的内容最后多一个逗号,这就需要用到<set>标签,会自动去除拼接的SQL最后多余的逗号。
<set>标签只在修改里面用。

<update id="updateUser">update smbms_user<!--直接使用set会导致最后拼接SQL时要修改的内容最后多一个逗号,这就需要用到<set>标签,会自动去除拼接的SQL最后多余的逗号<set>标签只在修改里面用--><set><if test="userCode!=null">userCode=#{userCode},</if><if test="userName!=null">userName=#{userName},</if><if test="userPassword!=null">userPassword=#{userPassword},</if><if test="gender!=null">userPassword= #{gender},</if><if test="birthday!=null">birthday= #{birthday},</if></set><where>id=#{id}</where>
</update>

2.3 删

执行刪除SQL的映射没什么要注意的,这里就省略了。

三、接口方法传递参数

3.1 单个参数

一个参数,一般是不会用@Param注解的。

dao层接口方法

public Provider findProviderById(Integer id);

SQL映射

<select id="findProviderById" resultMap="ProviderMap">select id,proCode,proName,proDesc from smbms_provider a where a.id=#{id}
</select>

3.2 多个参数

多个参数(两个及以上):必须使用注解,相当于给参数起别名,否则SQL映射文件不认。
注解:@Param(value=“proName”),value=可省略,给参数指定别名,并在SQL配置xml文件中使用别名#{proName},#{proDesc}
dao层接口方法

public List<Provider> findList(@Param("pname") String proName,@Param(value="pdesc") String proDesc);

SQL映射

<select id="findList" resultType="Provider">select id,proCode,proName,proDescfrom smbms_provider awhere proName like concat('%',#{pname},'%')and proDesc like concat('%',#{pdesc},'%')
</select>

3.3 对象参数

  1. 如果传的是一个实体类对象,则sql中可直接使用这个实体类对象的属性名。
  2. 如果传的实体类对象使用@Param注解起别名,则sql中必须使用#{别名.参数名}。

dao层接口方法

//这里一个参数,正常是不会用@Param注解的,只是为了演示在使用注解的前提下,在sql配置xml文件中必须使用#{别名.属性名}进行接收传递的参数
public int addProvider(@Param(value="pro") Provider provider);

SQL映射

<insert id="addProvider">insert into smbms_provider(proCode,proName,proDesc) values(#{pro.proCode},#{pro.proName},#{pro.proDesc})
</insert>

3.4 使用Map集合能存所有参数

dao层接口方法

public List<Provider> findListByMap(Map<String,Object> maps);

SQL映射

使用map的key作为参数进行传递

<select id="findListByMap" resultType="Provider"><!--使用map的key作为参数进行传递-->select id,proCode,proName,proDescfrom smbms_provider awhere proName like concat('%',#{name},'%')and proDesc like concat('%',#{desc},'%')
</select>

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

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

相关文章

嵌入式硬件篇---麦克纳姆轮轨迹偏移

麦克纳姆轮的轨迹偏移是机械结构、驱动系统、控制逻辑及外部环境等多因素共同作用的结果&#xff0c;其核心是各轮子的驱动力 / 运动状态无法按理论模型实现协同&#xff0c;导致车体实际运动与期望轨迹产生偏差。以下是具体影响因素的详细分析&#xff1a;一、机械结构偏差&am…

C语言安全函数分享

在日常写程序中有一些功能函数是可以重复使用的&#xff0c;在c语言的标准库里面也有对应的功能函数&#xff0c;但是那些功能函数有会有小问题然后我就整理了一下对应功能的安全函数的使用。其中前四个函数可以编译成一个动态库&#xff0c;然后在项目工程中只需要包含对应的头…

汽车之家联合HarmonyOS SDK,深度构建鸿蒙生态体系

汽车之家作为一家领先的汽车互联网公司&#xff0c;致力于打造服务全球的汽车生态科技平台&#xff0c;覆盖"看选买用换"的一站式购车体验。2023年12月底&#xff0c;汽车之家正式启动鸿蒙开发&#xff0c;并于2024年年底成功构建了完整的鸿蒙生态体系&#xff0c;涵…

深度学习驱动的订单簿分析与交易策略优化

订单簿数据特征与预处理方法 高频金融数据中&#xff0c;订单簿&#xff08;Order Book&#xff09;承载着市场参与者的实时交易意图。不同于K线数据的聚合特性&#xff0c;订单簿数据具有独特的时空特征&#xff1a; 多维层级结构&#xff1a;包含不同价格档位的买卖盘深度信息…

Redis--day9--黑马点评--分布式锁(二)

&#xff08;以下所有内容全部来自上述课程&#xff09; 分布式锁 1. Redisson功能介绍 基于setnx实现的分布式锁存在下面的问题&#xff1a; 不可重入&#xff1a;同一个线程无法多次获取同一把锁不可重试&#xff1a;获取锁只尝试一次就返回false&#xff0c;没有重试机…

ES入门教程 (python 版)

ES入门教程 1. 创建ES对象from elasticsearch import Elasticsearch # 实例化一个ip为localhost&#xff0c;端口为9200&#xff0c;允许超时一小时的es对象 es Elasticsearch(hosts"localhost",port9200,timeout3600) # 1. 创建 索引 index_name "test"…

Gateway中Forward配置+源码观赏

系列文章目录 文章目录系列文章目录一、ForwardPathFilter二、RouteToRequestUrlFilter三、ForwardRoutingFilteryaml forward配置gateway:routes:- id: user-route # uri: lb://useruri: forward:///user/indexpredicates:- Path/user/**- YoGET # filt…

BAS16XV2T1G ON安森美半导体 高速开关二极管 电子元器件IC

BAS16XV2T1G ON Semiconductor 高速开关二极管专业解析1. 产品技术档案BAS16XV2T1G是安森美半导体(ON Semiconductor)推出的高速开关二极管&#xff0c;采用SOT-523超微型封装&#xff08;1.60.80.95mm&#xff09;&#xff0c;专为现代高密度电子设备设计&#xff0c;以其超快…

亲测可用 [安卓]《神秘来电》V1.1无需登入无广告离线打开即用手机模拟发起虚假来电免费版

神秘来电是一款可以模拟虚拟电话的应用程序&#xff0c;它能够在用户需要的时候模拟各种来电&#xff0c;以便用户能够在尴尬的场合脱身。用户可以预设多个不同的来电号码和铃声&#xff0c;并可随时触发这些虚拟电话&#xff0c;在特殊情况下帮助用户摆脱尴尬。它为那些社交恐…

8.20 dp

lc73矩阵置零queue队列标记// 整行置零for(int y0; y<n; y) matrix[i][y] 0; // 整列置零for(int x0; x<m; x) matrix[x][j] 0; class Solution { public:void setZeroes(vector<vector<int>>& matrix) {int m matrix.size(), n matrix[0].size();//…

STL库——string(类模拟实现)

ʕ • ᴥ • ʔ づ♡ど &#x1f389; 欢迎点赞支持&#x1f389; 个人主页&#xff1a;励志不掉头发的内向程序员&#xff1b; 专栏主页&#xff1a;C语言&#xff1b; 文章目录 前言 一、基本框架 二、构造函数 三、析构函数 四、拷贝构造 五、运算符重载 5.1、赋值重载 5.2…

Linux I/O 多路复用实战:深入剖析 Select 与 Poll

## 引言:从“阻塞”的餐厅到“事件驱动”的盛宴 想象一下,你是一家小餐馆的服务员。餐厅只有5张桌子。你的工作流程是这样的:走到1号桌,问他们是否要点菜,然后站在那里等他们决定;等他们点完,再去2号桌,同样站在那里等... 如果1号桌的客人看菜单看了半个小时,那么其他…

【clion】cmake脚本1:调试脚本并构建Fargo项目win32版本

调试脚本并构建 【clion】visual studio的sln转cmakelist并使用clion构建32位 报错 "D:\Program Files\JetBrains\CLion 2022.3.1\bin\cmake\win\x64\bin\cmake.exe" --debugger --debugger-pipe=\\<

VS2005里的快捷键

VS2005是微软在2005发布的一款支持C、C#、.net开发语言的集成开发工具&#xff0c;它支持的C版本为C03&#xff0c;但不支持C11&#xff0c;到VS2013才支持大部分的C11(简称C11)&#xff0c;到VS2015 update3才完全支持C11。既然VS2005不支持C11&#xff0c;而智能指针是C11才引…

前后端联合实现文件下载,实现 SQL Server image 类型文件下载

1、前端 Vue3QualityFile.vue<script setup lang"ts" name"QualityFile"> ...... // 下载&#xff0c;实现 SQL Server image 类型文件下载 const onDownloadClick async (fileNo: string) > {// const result await qualityFileDownloadFileWi…

【OneAI】使用Rust构建的轻量AI网关

LLM网关 统一大模型API入口&#xff0c;使用一个令牌调用多家模型&#xff0c;无需切换API Key兼容OpenAI输入输出规范内置10提供商和50模型&#xff0c;开箱即用支持自动负载、限流、IP限制、Token用量限制等功能支持钉钉、飞书、企微消息预警支持对不同提供商设置代理支持主…

Jenkins服务器配置SSH

1. 创建Jenkins用户的SSH配置ssh-keygen -t rsa -b 4096 -f /tmp/jenkins_ssh_key -N ""2. 在Jenkins服务器上执行以下命令# 切换到root用户 sudo su -# 创建Jenkins用户的SSH目录 mkdir -p /var/lib/jenkins/.ssh chown jenkins:jenkins /var/lib/jenkins/.ssh chmo…

nginx-下载功能-状态统计-访问控制

nginx-下载功能-状态统计-访问控制一、利用nginx做网站提供下载功能1. 进入nginx存放配置文件目录2. 编辑nginx.conf文件&#xff0c;开启下载功能3. 检查nginx.conf主配置文件是否正确4. 重启nginx服务5. 修改首页文件index.html6. 访问首页7. 去网页根目录下新建download目录…

GitLab CI/CD、Jenkins与GitHub Actions在Kubernetes环境中的方案对比分析

GitLab CI/CD、Jenkins与GitHub Actions在Kubernetes环境中的方案对比分析 随着容器化和微服务的普及&#xff0c;基于Kubernetes的部署已经成为主流。在实际的生产环境中&#xff0c;如何选择合适的CI/CD流水线方案以实现自动化构建、测试、部署和发布&#xff0c;直接关系到团…

tcp会无限次重传吗

tcp作为面向连接的&#xff0c;可靠的&#xff0c;字节流。最重要的特点就是可靠&#xff0c;其中重传又是保证可靠的重要前提。那么当tcp发送数据之后&#xff0c;收不到ack的情况下&#xff0c;会无限次重传吗。不会。# cat /proc/sys/net/ipv4/tcp_retries1 3 # cat /proc/s…