Mybatis常用

news/2024/10/6 3:28:23/文章来源:https://www.cnblogs.com/zhangyf1121/p/18287411

Mybatis

1.forEach标签

foreach元素的属性主要有item,index,collection,open,separator,close。

  • item:集合中元素迭代时的别名,
  • index:集合中元素迭代时的索引
  • open:常用语where语句中,表示以什么开始,比如以'('开始
  • separator:表示在每次进行迭代时的分隔符,
  • close 常用语where语句中,表示以什么结束,

在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的,主要有一下3种情况:

  • 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list .
  • 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array .
  • 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key.

针对最后一条,我们来看一下官方说法:

注意 你可以将一个 List 实例或者数组作为参数对象传给 MyBatis,当你这么做的时候,MyBatis 会自动将它包装在一个 Map 中并以名称为键。List 实例将会以“list”作为键,而数组实例的键将是“array”。

所以,不管是多参数还是单参数的list,array类型,都可以封装为map进行传递。如果传递的是一个List,则mybatis会封装为一个list为key,list值为object的map,如果是array,则封装成一个array为key,array的值为object的map,如果自己封装呢,则colloection里放的是自己封装的map里的key值

//mapper中我们要为这个方法传递的是一个容器,将容器中的元素一个一个的
//拼接到xml的方法中就要使用这个forEach这个标签了
public List<Entity> queryById(List<String> userids);//对应的xml中如下<select id="queryById" resultMap="BaseReslutMap" >select * FROM entitywhere id in<foreach collection="userids" item="userid" index="index" open="(" separator="," close=")">#{userid}</foreach></select>

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

2.concat模糊查询

//比如说我们想要进行条件查询,但是几个条件不是每次都要使用,那么我们就可以
//通过判断是否拼接到sql中<select id="queryById" resultMap="BascResultMap" parameterType="entity">SELECT *  from entity<where><if test="name!=null">name like concat('%',concat(#{name},'%'))</if></where></select>

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

3.choose (when, otherwise)标签

choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql。类似于Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。

例如下面例子,同样把所有可以限制的条件都写上,方面使用。choose会从上到下选择一个when标签的test为true的sql执行。安全考虑,我们使用where将choose包起来,放置关键字多于错误。

<!--  choose(判断参数) - 按顺序将实体类 User 第一个不为空的属性作为:where条件 -->
<select id="getUserList_choose" resultMap="resultMap_user" parameterType="com.yiibai.pojo.User">SELECT *FROM User u<where><choose><when test="username !=null ">u.username LIKE CONCAT(CONCAT('%', #{username, jdbcType=VARCHAR}),'%')</when ><when test="sex != null and sex != '' ">AND u.sex = #{sex, jdbcType=INTEGER}</when ><when test="birthday != null ">AND u.birthday = #{birthday, jdbcType=DATE}</when ><otherwise></otherwise></choose></where>
</select>

4.selectKey 标签

在insert语句中,在Oracle经常使用序列、在MySQL中使用函数来自动生成插入表的主键,而且需要方法能返回这个生成主键。使用myBatis的selectKey标签可以实现这个效果。 下面例子,使用mysql数据库自定义函数nextval('student'),用来生成一个key,并把他设置到传入的实体类中的studentId属性上。所以在执行完此方法后,边可以通过这个实体类获取生成的key。

<!-- 插入学生 自动主键-->
<insert id="createStudentAutoKey" parameterType="liming.student.manager.data.model.StudentEntity" keyProperty="studentId"><selectKey keyProperty="studentId" resultType="String" order="BEFORE">select nextval('student')</selectKey>INSERT INTO STUDENT_TBL(STUDENT_ID,STUDENT_NAME,STUDENT_SEX,STUDENT_BIRTHDAY,STUDENT_PHOTO,CLASS_ID,PLACE_ID)VALUES (#{studentId},#{studentName},#{studentSex},#{studentBirthday},#{studentPhoto, javaType=byte[], jdbcType=BLOB, typeHandler=org.apache.ibatis.type.BlobTypeHandler},#{classId},#{placeId})
</insert>

调用接口方法,和获取自动生成key

StudentEntity entity = new StudentEntity();
entity.setStudentName("黎明你好");
entity.setStudentSex(1);
entity.setStudentBirthday(DateUtil.parse("1985-05-28"));
entity.setClassId("20000001");
entity.setPlaceId("70000001");
this.dynamicSqlMapper.createStudentAutoKey(entity);
System.out.println("新增学生ID: " + entity.getStudentId());

5.if标签

if标签可用在许多类型的sql语句中,我们以查询为例。首先看一个很普通的查询:

<!-- 查询学生list,like姓名 -->
<select id="getStudentListLikeName" parameterType="StudentEntity" resultMap="studentResultMap">SELECT * from STUDENT_TBL ST
WHERE ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')
</select>

但是此时如果studentName为null,此语句很可能报错或查询结果为空。此时我们使用if动态sql语句先进行判断,如果值为null或等于空字符串,我们就不进行此条件的判断,增加灵活性。

参数为实体类StudentEntity。将实体类中所有的属性均进行判断,如果不为空则执行判断条件。

<!-- 2 if(判断参数) - 将实体类不为空的属性作为where条件 -->
<select id="getStudentList_if" resultMap="resultMap_studentEntity" parameterType="liming.student.manager.data.model.StudentEntity">SELECT ST.STUDENT_ID,ST.STUDENT_NAME,ST.STUDENT_SEX,ST.STUDENT_BIRTHDAY,ST.STUDENT_PHOTO,ST.CLASS_ID,ST.PLACE_IDFROM STUDENT_TBL STWHERE<if test="studentName !=null ">ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName, jdbcType=VARCHAR}),'%')</if><if test="studentSex != null and studentSex != '' ">AND ST.STUDENT_SEX = #{studentSex, jdbcType=INTEGER}</if><if test="studentBirthday != null ">AND ST.STUDENT_BIRTHDAY = #{studentBirthday, jdbcType=DATE}</if><if test="classId != null and classId!= '' ">AND ST.CLASS_ID = #{classId, jdbcType=VARCHAR}</if><if test="classEntity != null and classEntity.classId !=null and classEntity.classId !=' ' ">AND ST.CLASS_ID = #{classEntity.classId, jdbcType=VARCHAR}</if><if test="placeId != null and placeId != '' ">AND ST.PLACE_ID = #{placeId, jdbcType=VARCHAR}</if><if test="placeEntity != null and placeEntity.placeId != null and placeEntity.placeId != '' ">AND ST.PLACE_ID = #{placeEntity.placeId, jdbcType=VARCHAR}</if><if test="studentId != null and studentId != '' ">AND ST.STUDENT_ID = #{studentId, jdbcType=VARCHAR}</if>
</select>

使用时比较灵活, new一个这样的实体类,我们需要限制那个条件,只需要附上相应的值就会where这个条件,相反不去赋值就可以不在where中判断。

public void select_test_2_1() {StudentEntity entity = new StudentEntity();entity.setStudentName("");entity.setStudentSex(1);entity.setStudentBirthday(DateUtil.parse("1985-05-28"));entity.setClassId("20000001");//entity.setPlaceId("70000001");List<StudentEntity> list = this.dynamicSqlMapper.getStudentList_if(entity);for (StudentEntity e : list) {System.out.println(e.toString());}
}

6.if + where 的条件判断

当where中的条件使用的if标签较多时,这样的组合可能会导致错误。我们以在3.1中的查询语句为例子,当java代码按如下方法调用时:

@Test
public void select_test_2_1() {StudentEntity entity = new StudentEntity();entity.setStudentName(null);entity.setStudentSex(1);List<StudentEntity> list = this.dynamicSqlMapper.getStudentList_if(entity);for (StudentEntity e : list) {System.out.println(e.toString());}
}

如果上面例子,参数studentName为null,将不会进行STUDENT_NAME列的判断,则会直接导“WHERE AND”关键字多余的错误SQL。 这时我们可以使用where动态语句来解决。这个“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。 上面例子修改为:

<!-- 3 select - where/if(判断参数) - 将实体类不为空的属性作为where条件 -->
<select id="getStudentList_whereIf" resultMap="resultMap_studentEntity" parameterType="liming.student.manager.data.model.StudentEntity">SELECT ST.STUDENT_ID,ST.STUDENT_NAME,ST.STUDENT_SEX,ST.STUDENT_BIRTHDAY,ST.STUDENT_PHOTO,ST.CLASS_ID,ST.PLACE_IDFROM STUDENT_TBL ST<where><if test="studentName !=null ">ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName, jdbcType=VARCHAR}),'%')</if><if test="studentSex != null and studentSex != '' ">AND ST.STUDENT_SEX = #{studentSex, jdbcType=INTEGER}</if><if test="studentBirthday != null ">AND ST.STUDENT_BIRTHDAY = #{studentBirthday, jdbcType=DATE}</if><if test="classId != null and classId!= '' ">AND ST.CLASS_ID = #{classId, jdbcType=VARCHAR}</if><if test="classEntity != null and classEntity.classId !=null and classEntity.classId !=' ' ">AND ST.CLASS_ID = #{classEntity.classId, jdbcType=VARCHAR}</if><if test="placeId != null and placeId != '' ">AND ST.PLACE_ID = #{placeId, jdbcType=VARCHAR}</if><if test="placeEntity != null and placeEntity.placeId != null and placeEntity.placeId != '' ">AND ST.PLACE_ID = #{placeEntity.placeId, jdbcType=VARCHAR}</if><if test="studentId != null and studentId != '' ">AND ST.STUDENT_ID = #{studentId, jdbcType=VARCHAR}</if></where>
</select>

7.if + set实现修改语句

当update语句中没有使用if标签时,如果有一个参数为null,都会导致错误。 当在update语句中使用if标签时,如果前面的if没有执行,则或导致逗号多余错误。使用set标签可以将动态的配置SET 关键字,和剔除追加到条件末尾的任何不相关的逗号。使用if+set标签修改后,如果某项为null则不进行更新,而是保持数据库原值。如下示例:

<!-- 4 if/set(判断参数) - 将实体类不为空的属性更新 -->
<update id="updateStudent_if_set" parameterType="liming.student.manager.data.model.StudentEntity">UPDATE STUDENT_TBL<set><if test="studentName != null and studentName != '' ">STUDENT_TBL.STUDENT_NAME = #{studentName},</if><if test="studentSex != null and studentSex != '' ">STUDENT_TBL.STUDENT_SEX = #{studentSex},</if><if test="studentBirthday != null ">STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday},</if><if test="studentPhoto != null ">STUDENT_TBL.STUDENT_PHOTO = #{studentPhoto, javaType=byte[], jdbcType=BLOB, typeHandler=org.apache.ibatis.type.BlobTypeHandler},</if><if test="classId != '' ">STUDENT_TBL.CLASS_ID = #{classId}</if><if test="placeId != '' ">STUDENT_TBL.PLACE_ID = #{placeId}</if></set>WHERE STUDENT_TBL.STUDENT_ID = #{studentId};
</update>

8.if + trim代替where/set标签

trim是更灵活的去处多余关键字的标签,他可以实践where和set的效果。

trim代替where

<!-- 5.1if/trim代替where(判断参数) -将实体类不为空的属性作为where条件-->
<select id="getStudentList_if_trim" resultMap="resultMap_studentEntity">SELECT ST.STUDENT_ID,ST.STUDENT_NAME,ST.STUDENT_SEX,ST.STUDENT_BIRTHDAY,ST.STUDENT_PHOTO,ST.CLASS_ID,ST.PLACE_IDFROM STUDENT_TBL ST<trim prefix="WHERE" prefixOverrides="AND|OR"><if test="studentName !=null ">ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName, jdbcType=VARCHAR}),'%')</if><if test="studentSex != null and studentSex != '' ">AND ST.STUDENT_SEX = #{studentSex, jdbcType=INTEGER}</if><if test="studentBirthday != null ">AND ST.STUDENT_BIRTHDAY = #{studentBirthday, jdbcType=DATE}</if><if test="classId != null and classId!= '' ">AND ST.CLASS_ID = #{classId, jdbcType=VARCHAR}</if><if test="classEntity != null and classEntity.classId !=null and classEntity.classId !=' ' ">AND ST.CLASS_ID = #{classEntity.classId, jdbcType=VARCHAR}</if><if test="placeId != null and placeId != '' ">AND ST.PLACE_ID = #{placeId, jdbcType=VARCHAR}</if><if test="placeEntity != null and placeEntity.placeId != null and placeEntity.placeId != '' ">AND ST.PLACE_ID = #{placeEntity.placeId, jdbcType=VARCHAR}</if><if test="studentId != null and studentId != '' ">AND ST.STUDENT_ID = #{studentId, jdbcType=VARCHAR}</if></trim>
</select>

trim代替set

<!-- 5.2 if/trim代替set(判断参数) - 将实体类不为空的属性更新 -->
<update id="updateStudent_if_trim" parameterType="liming.student.manager.data.model.StudentEntity">UPDATE STUDENT_TBL<trim prefix="SET" suffixOverrides=","><if test="studentName != null and studentName != '' ">STUDENT_TBL.STUDENT_NAME = #{studentName},</if><if test="studentSex != null and studentSex != '' ">STUDENT_TBL.STUDENT_SEX = #{studentSex},</if><if test="studentBirthday != null ">STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday},</if><if test="studentPhoto != null ">STUDENT_TBL.STUDENT_PHOTO = #{studentPhoto, javaType=byte[], jdbcType=BLOB, typeHandler=org.apache.ibatis.type.BlobTypeHandler},</if><if test="classId != '' ">STUDENT_TBL.CLASS_ID = #{classId},</if><if test="placeId != '' ">STUDENT_TBL.PLACE_ID = #{placeId}</if></trim>WHERE STUDENT_TBL.STUDENT_ID = #{studentId}
</update>

9.foreach

对于动态SQL 非常必须的,主是要迭代一个集合,通常是用于IN 条件。List 实例将使用“list”做为键,数组实例以“array” 做为键。

foreach元素是非常强大的,它允许你指定一个集合,声明集合项和索引变量,它们可以用在元素体内。它也允许你指定开放和关闭的字符串,在迭代之间放置分隔符。这个元素是很智能的,它不会偶然地附加多余的分隔符。

注意:你可以传递一个List实例或者数组作为参数对象传给MyBatis。当你这么做的时候,MyBatis会自动将它包装在一个Map中,用名称在作为键。List实例将会以“list”作为键,而数组实例将会以“array”作为键。

这个部分是对关于XML配置文件和XML映射文件的而讨论的。下一部分将详细讨论Java API,所以你可以得到你已经创建的最有效的映射。

参数为array示例的写法

接口的方法声明:

public List<StudentEntity> getStudentListByClassIds_foreach_array(String[] classIds);

动态SQL语句:

<!— 7.1 foreach(循环array参数) - 作为where中in的条件 -->
<select id="getStudentListByClassIds_foreach_array" resultMap="resultMap_studentEntity">SELECT ST.STUDENT_ID,ST.STUDENT_NAME,ST.STUDENT_SEX,ST.STUDENT_BIRTHDAY,ST.STUDENT_PHOTO,ST.CLASS_ID,ST.PLACE_IDFROM STUDENT_TBL STWHERE ST.CLASS_ID IN<foreach collection="array" item="classIds"  open="(" separator="," close=")">#{classIds}</foreach>
</select>

测试代码,查询学生中,在20000001、20000002这两个班级的学生:

@Test  public void test7_foreach() {      String[] classIds = { "20000001", "20000002" };      List<StudentEntity> list = this.dynamicSqlMapper.getStudentListByClassIds_foreach_array(classIds);      for (StudentEntity e : list) {          System.out.println(e.toString());      }  }

2参数为list示例的写法 接口的方法声明:

public List<StudentEntity> getStudentListByClassIds_foreach_list(List<String> classIdList);

动态SQL语句:

<!-- 7.2 foreach(循环List<String>参数) - 作为where中in的条件 -->
<select id="getStudentListByClassIds_foreach_list" resultMap="resultMap_studentEntity">SELECT ST.STUDENT_ID,ST.STUDENT_NAME,ST.STUDENT_SEX,ST.STUDENT_BIRTHDAY,ST.STUDENT_PHOTO,ST.CLASS_ID,ST.PLACE_IDFROM STUDENT_TBL STWHERE ST.CLASS_ID IN<foreach collection="list" item="classIdList"  open="(" separator="," close=")">#{classIdList}</foreach>
</select>

测试代码,查询学生中,在20000001、20000002这两个班级的学生:

@Test
public void test7_2_foreach() {ArrayList<String> classIdList = new ArrayList<String>();classIdList.add("20000001");classIdList.add("20000002");List<StudentEntity> list = this.dynamicSqlMapper.getStudentListByClassIds_foreach_list(classIdList);for (StudentEntity e : list) {System.out.println(e.toString());}

sql片段标签:通过该标签可定义能复用的sql语句片段,在执行sql语句标签中直接引用即可。这样既可以提高编码效率,还能有效简化代码,提高可读性

需要配置的属性:id="" >>>表示需要改sql语句片段的唯一标识

引用:通过标签引用,refid="" 中的值指向需要引用的中的id=“”属性

<!--定义sql片段-->
<sql id="orderAndItem">o.order_id,o.cid,o.address,o.create_date,o.orderitem_id,i.orderitem_id,i.product_id,i.count</sql><select id="findOrderAndItemsByOid" parameterType="java.lang.String" resultMap="BaseResultMap">select
<!--引用sql片段--><include refid="orderAndItem" />from ordertable ojoin orderitem i on o.orderitem_id = i.orderitem_idwhere o.order_id = #{orderId}</select>

10.分步查询

定义:需要根据用户id去查询角色表对应的信息,一种做法是直接用关联查询,另一种就分步查询,先查询

到用户信息。然后再把用户信息中的id取出来作为条件去角色表查出对应的角色信息。

1.查询User

public interface UserDao {// 根据用户名查询用户,并且要求把该用户所具有的角色信息也查询出来User findByUserName(String username);    
}
<resultMap id="userMap" type="User"><id column="id" property="id"></id><result column="username" property="username"></result><result column="age" property="age"></result><result column="address" property="address"></result>
</resultMap><resultMap id="UserRoleMapBySelect" type="User" extends="userMap"><connection property="roles"ofType="Role"<!-- 查询roles的数据(调用哪个方法)-->select="包名+接口名+方法名(findRoleByUserId)"<!-- 把当前结果集的哪个数据作为参数传递过去 -->column="id"> <!-- 这边的id就对应下面select中的id --></connection>
</resultMap><!-- 根据用户名查询用户,并且要求把该用户所具有的角色信息也查询出来 -->
<select id="findByUserName" resultMap="UserRoleMapBySelect">select id, username, age, address from user where username= #{username}
</select>

2.根据user_id查询Role

public interface RoleDao{// 根据userId查询所有的角色List<Role> findRoleByUserId(Integer userId);
}
<!-- 根据userId查询所有的角色 -->
<select id="findRoleByUserId" resultType="Role">select r.id, r.name, r.desc from role r, user_role urwhereur.role_id = r.idand ur.user_id = #{ userId }
</select>

3.获取到之前查询到userId传入到上面的#{ userId }中

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

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

相关文章

数据结构小学期第六天

今天完全实现了九宫格拼图游戏,具备一键通关功能按下W键,查看原图功能按住A键不松,移动图片按上下左右键,如果你自己想要实现这个功能,需要自己的图片,图片格式要求。 每个小图片是105*105,完整图片是315*315.有人想要做一下,可以试一试。代码如下 启动类1 import com.…

1、flask-基本架构-MVT - 虚拟环境的安装 - 创建flask应用

flask基本架构图 创建虚拟环境 #1. 打开cmd或pycharm都可以(确保安装python环境) #2. 安装虚拟环境模块-windows - pip install virtualenv virtualenvwrapper-win#3. 查看虚拟环境 - workon#4. 创建虚拟环境 - mkvirtualenv flask2env - 默认创建在:C:\Users\Administrato…

基于Qwen2/Lllama3等大模型,部署团队私有化RAG知识库系统的详细教程(Docker+AnythingLLM)

大语言模型在垂直细分领域存在知识局限、幻觉、数据安全等一些问题,可通过RAG(检索增强生成)方案来解决。本文基于AnythingLLM框架,搭建团队私有知识库系统,并进行使用和验证,RAG系统在保留输出的有效性同时,还保留了创造性……自 ChatGPT 发布以来,大型语言模型(Larg…

基于STM32F1系列,驱动L298N电机驱动板实现直流电机的启动、停止、调速功能

一. L298N电机驱动板电源引脚 VCC 外接直流电源引脚,电压范围在5~35V之间 GND GND是接地引脚,连接到电源负极 5V 驱动芯片内部逻辑供电引脚,如果安装了5V跳帽,则此引脚可输出5V电压,为微控板或其他电路提供电力供给,如果拔掉5V跳帽,则需要独立外接5V电源 控制引脚 IN1 &…

SpringBoot引入WebSocket

WebSocket 是一种在客户端和服务器之间提供低延迟、全双工通信的网络协议。它允许双方在建立一次连接后,进行实时、持续的数据交换,无需像HTTP那样为每一个请求和响应建立新的连接。WebSocket的设计初衷是解决传统HTTP协议在实时通信方面的不足,比如实现实时聊天、游戏、股票…

博客园商业之路:全园求偶遇,懂园子懂商业的创业合伙人

各方面的因素将园子的商业化强推到一个关口,2024年7月-9月是决定园子命运的一个季度,我们将拼尽所有力气找各种可能的突破口,不会有任何保留。 这个关口是最后关头,也是三年多来最好的时间窗口,天时地利最需要人和,找到对的人,最有可能在这个时间窗口,一将解园子二十年…

KBPC2504-ASEMI无人机专用整流桥KBPC2504

KBPC2504-ASEMI无人机专用整流桥KBPC2504编辑:ll KBPC2504-ASEMI无人机专用整流桥KBPC2504 型号:KBPC2504 品牌:ASEMI 封装:KBPC-4 最大重复峰值反向电压:400V 最大正向平均整流电流(Vdss):25A 功率(Pd):中小功率 芯片个数:4 引脚数量:4 类型:整流方桥、整流桥 正向浪…

3款C#开源且实用的工具类库,工作效率提升利器!

前言 在日常工作开发中工具类库是软件开发中不可或缺的一部分,它们通过提供代码重用、通用功能、隐藏复杂性、提高代码质量、扩展性等方面的优势,帮助开发者更高效、更稳定地构建软件应用程序。今天大姚给大家分享3款C#开源且实用的工具类库,希望能帮助到有需要的小伙伴。 M…

关于 Puerts 的性能问题

Puerts 在 UE 开发中提供了一定的便利性,可以用代码的方式写蓝图,但是官方是不推荐这么做的 原话如下那么这个性能问题究竟有多大呢 这里先用 C++ 写一个测试代码#include "TestWidget.h"#include "Blueprint/WidgetBlueprintLibrary.h" #include "…

均方误差、二元交叉熵推导

详情可以看:https://zhuanlan.zhihu.com/p/626054495

MinGW GCC Windows下编译libmodbus

最近项目从MSVC切换到GCC,libmodbus官网没提供MinGW下GCC 如何编译,官网推荐在类UNIX环境下MSYS下编译,个人更偏向直接拿源文件编译。 编译libmodbus版本: libmodbus-3.1.10 GCC编译器版本: 5.3.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project) CMake版本: 3.29.0 1…

提取时序数据的趋势、季节性以及残差

一天的光滑数据sub = [199.68, 187.16, 173.97, 159.85, 146.92, 135.29, 125.04, 114.86, 105.85, 97.93, 90.6, 84.19, 78.37, 72.85, 68.93, 66.59, 62.19, 58.59, 54.15, 50.26, 47.16, 44.14, 41.62, 38.99, 36.84, 34.9, 33.32, 32.75, 33.1, 32.49, 31.49, 30.13, 28.96…