Mybatis的基本使用

什么是Mybatis?

  1. Mybatis是一个简化JDBC的持久层框架,MyBatis是一个半自动化框架,是因为它在SQL执行过程中只提供了基本的SQL执行功能,而没有像Hibernate那样将所有的ORM操作都自动化了。在MyBatis中,需要手动编写SQL语句,但是它提供了很多便捷的操作,例如参数映射、结果集映射、缓存机制等等,使得开发者能够更加灵活地操作SQL。此外,MyBatis还提供了许多插件机制,可以对SQL执行流程进行拦截和修改,以满足各种不同的需求。这也是MyBatis相对于其他ORM框架的一个优点。
  2. 持久层:负责将数据保存到数据库的那一层代码
  3. JavaEE三层架构:表现层,业务层,持久层
  4. 框架:写好部分代码的半成品软件

JDBC的缺点:

  1. 硬编码:
    • 注册驱动,获取连接的那部分代码不灵活,改变的时候会很麻烦
    • 写死的SQL语句没有那么灵活
  2. 操作繁琐
    • 需要手动设置参数(prepareStatement)
    • 手动封装结果集(resultSet)

Mybatis的优点

  1. 硬编码–》利用**配置文件(xml)**可以减少硬编码的编写
  2. 操作繁琐–》底层自动完成参数的设置以及结果集的封装
  3. Mybatis 免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作

Mybatis快速入门(mybatis-demo)

  • 非maven项目要使用 MyBatis, 只需将 mybatis-x.x.x.jar文件置于类路径(classpath)中即可。
  • 如果使用 Maven 来构建项目,则需将下面的依赖代码置于 pom.xml 文件中

Mapper代理开发:

使用Mapper代理方式,必须满足以下要求:

  1. 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下(紧对于使用包扫描方式映射xml文件)。如下图:
    在这里插入图片描述
    注意:这里的UserMapper.xml里面的内容可以到mybatis官网上面粘贴进来的,然后加以修改一下就能成为我们自己的代码了
<?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="com.knife.mapper.BrandMapper"><!--  只有这里namespace的路径是需要修改的  -->
</mapper>
  1. 设置SQL映射文件的namespace属性为Mapper接口全限定名(即对应mapper接口的路径)
    在这里插入图片描述
  2. 在 Mapper 接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致
    在这里插入图片描述
  • 注意:
    • 如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载(即在mybatis-config.xml文件下配置)。也就是将核心配置文件的加载映射配置文件的配置修改为
<mappers>
<!--加载sql映射文件-->
<!-- <mapper resource="com/itheima/mapper/UserMapper.xml"/>-->
<!--Mapper代理方式-->
<package name="com.itheima.mapper"/>
</mappers>

Mybatis的核心配置(mybatis-config.xml)

在这里插入图片描述

环境配置

  1. 在核心配置文件的 environments 标签中其实是可以配置多个 environment ,使用 id 给每段环境起名,在environments 中使用 default=‘环境id’ 来指定使用哪儿段配置。我们一般就配置一个 environment 即可。
<environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><!--数据库连接信息--><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/db1?useSSL=false&amp;serverTimeZone=UTC"/><property name="username" value="root"/><property name="password" value="1234"/></dataSource></environment><environment id="test"><transactionManager type="JDBC"/><dataSource type="POOLED"><!--数据库连接信息--><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/db1?useSSL=false&amp;serverTimeZone=UTC"/><property name="username" value="root"/><property name="password" value="1234"/></dataSource></environment>
</environments>
  1. 类型别名
    在映射配置文件中的 resultType 属性需要配置数据封装的类型(类的全限定名(即类的路径))。而每次这样写是特别麻烦的,Mybatis提供了 类型别名 (typeAliases) 可以简化这部分的书写。
    首先需要现在核心配置文件中配置类型别名,也就意味着给pojo包下所有的类起了别名(默认的别名就是:实体类名),不区分大小写。
    内容如下:
<typeAliases><!--name属性的值是实体类所在包--><package name="com.itheima.pojo"/>
</typeAliases>

通过上述的配置,我们就可以简化映射配置文件中 resultType 属性值的编写

<mapper namespace="com.itheima.mapper.UserMapper"><select id="selectAll" resultType="user">select * from tb_user;</select>
</mapper>

配置各个标签需要遵循前后顺序(即上面图片的那个顺序)

一、查询

1、查询所有

实体类属性名和数据库表的列名不一致,则idea不能自动封装数据

解决方法:

 * 方法一: 起别名 :对不一样的字段名起别名,让别名和实体类的属性名一样- 缺点:每次查询都要定义一次别名
<select id="selectAll" resultType="brand">select id , brand_name as brandName, company_name as companyName, ordered,description,status  from tb_brand;
</select>* 解决方法:使用sql片段<sql id="brand_column">id , brand_name as brandName, company_name as companyName, ordered,description,status</sql><select id="selectAll" resultType="brand">select  <include refid="brand_column"></include> from tb_brand;</select>* 缺点:sql片段不灵活-解决:方法二* 方法二:resultMap:1. 在<mapper namespace="com.itheima.mapper.BrandMapper"></mapper>标签中定义resultMap标签2. 在<select>标签中使用resultMap属性替换resultType属性<!--id: 唯一标识type:映射的类型(支持别名)--><resultMap id="brandResultMap" type="brand"><!--id:完成主键字段的映射result:完成一般字段的映射column: 该字段在数据库中的列名property: 该字段在实体类pojo的属性名<id column="brand_name" property="brandName"/>//主键字段的映射--><result column="brand_name" property="brandName"/><result column="company_name" property="companyName"/></resultMap>

2、Id查询

<!--*参数占位符:1. #{};会替换为 ?, 为了防止SQl注入2. ${}; 拼sql语句,会存在sql注入问题3. 使用时机:* 参数传递的时候,使用#{}* 数据库表名或者列名不固定的时候,使用${}* 参数类型:parameterType="int";可以省略<select id="selectById" parameterType="int" resultMap="brandResultMap">select * from tb_brand where id = ${id};</select>* 特殊字符处理:1. 转移字符:<select id="selectById" resultMap="brandResultMap">select * from tb_brand where id &lt; ${id};</select>2. CDATA区://其实就相当于文本框;<![CDATA[ 这里就是填数据的地方 ]]><select id="selectById" resultMap="brandResultMap">select * from tb_brand where id <![CDATA[ < ]]> ${id};</select>-->

3、多条件查询

//    多条件查询/***  * 参数接收:*      1. 散装参数:如果方法中有!!!多个参数!!!,需要使用@Param("sql参数占位符名称")*      2. 对象参数: 对象的属性名称要和参数占位符名称一致*      3. map集合: 只需保证sql中的参数名和map集合的键的名称对应上* @param status* @param companyName* @param brandName* @return*/
//    List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName, @Param("brandName") String brandName);
//    List<Brand> selectByCondition(Brand brand);List<Brand> selectByCondition(Map map);

一、动态查询

  • 动态sql:sql语句会随着用户的输入或者外部条件的变化而变化
<!--动态条件查询* if : 条件查询* test : 逻辑表达式* 产生的问题:第一个条件不需要逻辑运算符<if test="companyName !=null and companyName !='' ">and company_name like #{companyName}</if>*解决1: 多写一个恒等式: 1=1<select id="selectByCondition" resultMap="brandResultMap">select * from tb_brandwhere 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></select>*解决二:where标签替换where--><select id="selectByCondition" resultMap="brandResultMap">select * from tb_brandwhere<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></select>
//上面的一段代码单单用一个if标签是不能满足需求的),存在的问题是where后面的第一个条件不需要and,所以很难满足
//使用动态sql就可以解决<select id="selectByCondition" resultMap="brandResultMap">select * from tb_brand<where><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></select>

一、动态查询——单条件查询

<select id="selectByConditionSingle" resultMap="brandResultMap">select * from tb_brandwhere<choose> <!--相当于swith--><when test="status !=null"><!--相当于case-->status =#{status}</when><when test="companyName !=null and companyName !=''"><!--相当于case-->company_name like #{companyName}</when><when test="brandName !=null and brandName !=''"><!--相当于case-->brand_name like #{brandName}</when><otherwise> <!--相当于default-->1=1</otherwise></choose></select>//查询单个的
<select id="selectByConditionSingle" resultMap="brandResultMap">select * from tb_brandwhere<choose> <!--相当于swith--><when test="status !=null"><!--相当于case-->status =#{status}</when><when test="companyName !=null and companyName !=''"><!--相当于case-->company_name like #{companyName}</when><when test="brandName !=null and brandName !=''"><!--相当于case-->brand_name like #{brandName}</when><otherwise> <!--相当于defaut-->1=1</otherwise></choose></select>
//使用where标签的改进
<select id="selectByConditionSingle" resultMap="brandResultMap">select * from tb_brand<where><choose> <!--相当于swith--><when test="status !=null"><!--相当于case-->status =#{status}</when><when test="companyName !=null and companyName !=''"><!--相当于case-->company_name like #{companyName}</when><when test="brandName !=null and brandName !=''"><!--相当于case-->brand_name like #{brandName}</when></choose></where></select>

二、添加数据

添加

public void testAdd() throws IOException {
//        1.接收参数int status=1;String companyName="华为";String brandName ="波导";String description="手机中的战斗机";int ordered=100;//        封装参数Brand brand = new Brand();brand.setStatus(status);brand.setBrandName(brandName);brand.setCompanyName(companyName);brand.setDescription(description);brand.setOrdered(ordered);//        Map集合
//        Map map = new HashMap();
//        map.put("status",status);
//        map.put("companyName",companyName);
//        map.put("brandName",brandName);//        1. 获取SqlSessionFactory对象String resource = "mybatis-config.xml";//配置文件的路径InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//        2. 获取SqlSession对象
//        SqlSession sqlSession = sqlSessionFactory.openSession(); //默认开启事务,进行增删改查需要使用sqlSession.commit();手动提交事务SqlSession sqlSession = sqlSessionFactory.openSession(true);//设置自动提交事务 
//        3. 获取Mapper对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);brandMapper.add(brand);
//        手动提交事务sqlSession.commit();
//        5. 释放资源sqlSession.close();}

添加-----主键返回

  • 默认没有主键返回的(即id)
<insert id="add">insert into tb_brand(brand_name, company_name,ordered,description,status)values (#{companyName},#{brandName},#{ordered},#{description},#{status});</insert>//其实当我们指向这个sql语句的时候,id值就已经存在的了,只是没有直接绑定到该对象里面,我们没有去获取而已,下面的代码就是获取id值(这里id是主键)
  • 有主键返回
//获取到主键值后,将来就可以通过该实体类对象对应的get方法得到
<!--keyProperty指向主键名--><insert id="add" useGeneratedKeys="true" keyProperty="id">insert into tb_brand(brand_name, company_name,ordered,description,status)values (#{companyName},#{brandName},#{ordered},#{description},#{status});</insert>

三、修改

三、1、修改全部字段

<!--    修改全部字段--><update id="update">update tb_brandset brand_name = #{brandName},company_name = #{companyName},ordered = #{ordered},description = #{description},status = #{status}where id =#{id};</update>

三、2、修改动态字段(将来修改哪个字段是不固定的)

  • 原来的:
 <update id="update">update tb_brandset brand_name = #{brandName},company_name = #{companyName},ordered = #{ordered},description = #{description},status = #{status}where id =#{id};</update>
  • 使用动态sql
<!--    修改动态sql--><update id="update">update tb_brand<set><if test="brandName != null and brandName !='' ">brand_name = #{brandName},</if><if test="companyName != null and companyName !=''">company_name = #{companyName},</if><if test="ordered != null">ordered = #{ordered},</if><if test="description != null and description != ''">description = #{description},</if><if test="status != null">status = #{status}</if></set>where id =#{id};</update>

四、删除

四、1、删除一条记录

<!--   根据id进行 删除--><delete id="deleteById">delete from tb_brand where id = #{id};</delete>

四、2、批量删除

  1. 使用数组进行作为参数
<!--    批量删除-->
<!--    mybatis会将数组参数封装到一个Map集合* 默认key名字:array* 可以用  @Param("ids")注解改变map集合的默认key(map里面的键)名称* 1.collection:要遍历的目标集合* open:循环开始时的字符;close:循环结束时的字符* item:遍历出的集合成员,自己定义的变量* separator:结合成员之间的分隔符* #{item}:注意与item="item"中的的值相同(即变量名要相同)
--><delete id="deleteByIds">delete from tb_brand where idin (<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach>);</delete>

Mybatis参数传递

Mybatis接口方法中可以接收各种各样的参数,Mybatis底层对于这些参数进行不同的封装处理方式

1.单个参数的封装:

-参数是 POJO类型:直接使用,实体类属性名和参数占位符名称一致

  • 参数是 Map集合:直接使用,键名 和参数占位符一致
  • 参数是 Collection:封装为Map集合
//两种方法
map.put("collection",collection集合);
map.put("arg0",collection集合);
  • 参数是 List:封装为Map集合
map.put("collection",list集合);
map.put("list",list集合);
map.put("arg0",list集合);
  • 参数是 Array:封装为Map集合
map.put("array",数组);
map.put("arg0",数组);
  • 参数是 其它类型:直接使用

2.多个参数:

多个参数会被封装为map集合,可以使用@param()注解,来替换map集合中默认的arg键名

//两种
map.put("arg0",参数值1);
map.put("arg1",参数值2);map.put("param1",参数值1);
map.put("param2",参数值2);
  • 建议:将来都使用@Param注解来修改Map集合(多个参数,系统会默认把参数封装成集合)中的默认键名,并使用修改后的名称来获取值,这样可读性更高
    • 首先明确这个@Param注解是为SQL语句中参数赋值而服务的。
      @Param的作用就是给参数命名,比如在mapper里面某方法A(int id),当添加注解后A(@Param(“userId”) int id),也就是说外部想要取出传入的id值,只需要取它的参数名userId就可以了。将参数值传如SQL语句中,通过#{userId}进行取值给SQL的参数赋值。

实例一:@Param注解基本类型的参数

    1. mapper中的方法:
public User selectUser(@Param("userName") String name,@Param("password") String pwd);

映射到xml中的标签

<select id="selectUser" resultMap="User">  select * from user  where user_name = #{userName} and user_password=#{password}  
</select>
  • 其中where user_name = #{userName} and user_password = #{password}中的userName和password都是从注解@Param()里面取出来的,取出来的值就是方法中形式参数 String name 和 String pwd的值。
当使用了@Param注解来声明参数的时候,SQL语句取值使用#{}, ${}取值都可以。
当不使用@Param注解声明参数的时候,必须使用的是#{}来取参数。使用${}方式取值会报错。

注解开发

  1. 使用注解开发会比配置文件开发更加简单方便
  • 查询:@Select
  • 添加:@Insert
  • 修改:@Update
  • 删除:@Delete
    提示:注解开发完成简单功能,配置文件开发完成复杂功能
  1. xml开发,需要配置xml文件中设置
 <select id="selectById" resultType="user">select * from tb_user where id =#{id};</select>

在这里插入图片描述
注解开发:
在这里插入图片描述

  • 使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。
  • 选择何种方式来配置映射,以及认为是否应该要统一映射语句定义的形式,完全取决于你和你的团队。 换句话说,永远不要拘泥于一种方式,你可以很轻松的在基于注解和 XML 的语句映射方式间自由移植和切换。

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

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

相关文章

第十三章 集合

一、集合的概念 集合&#xff1a;将若干用途、性质相同或相近的“数据”组合而成的一个整体 Java集合中只能保存引用类型的数据&#xff0c;不能保存基本类型数据 数组的缺点&#xff1a;长度不可变 Java中常用集合&#xff1a; 1.Set(集):集合中的对象不按特定方式排序&a…

工具模块及项目整体模块框架

文章目录 工具模块logger.hpphelper.hppthreadpool.hpp 核心概念核心API交换机类型持久化⽹络通信消息应答持久化数据管理中心模块虚拟机管理模块交换路由模块消费者管理模块信道管理模块连接管理模块Broker服务器模块消费者管理信道请求模块通信连接模块项⽬模块关系图 工具模…

ScrapeGraphAI 大模型增强的网络爬虫

在数据驱动的动态领域&#xff0c;从在线资源中提取有价值的见解至关重要。从市场分析到学术研究&#xff0c;对特定数据的需求推动了对强大的网络抓取工具的需求。 NSDT工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线…

电脑出现msvcp140.dll丢失的解决方法,总结6种解决方法

在计算机使用过程中&#xff0c;我们常常会遇到一些错误提示&#xff0c;其中最常见的就是“msvcp140.dll丢失”的错误。这个错误提示通常出现在运行某个程序时&#xff0c;它意味着计算机无法找到所需的msvcp140.dll文件。那么&#xff0c;msvcp140.dll丢失是怎么回事呢&#…

69 BERT预训练_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录NLP里的迁移学习Bert的动机Bert架构对输入的修改五、预训练任务1、2、3、 六、1、2、3、 七、1、2、3、 八、1、2、3、 NLP里的迁移学习 之前是使用预训练好的模型来抽取词、句子的特征&#xff0c;例如 word2vec 或语言模型这种非深度学习…

银河麒麟V10如何关闭定期锁屏功能?

银河麒麟V10如何关闭定期锁屏功能? 1. 打开终端2. 执行命令3. 验证设置 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在银河麒麟高级服务器操作系统V10中&#xff0c;关闭定期锁屏功能很简单。使用场景&#xff1a;比如&#xff0c;当你…

大模型~合集6

我自己的原文哦~ https://blog.51cto.com/whaosoft/11566566 # 深度模型融合&#xff08;LLM/基础模型/联邦学习/微调等&#xff09; 23年9月国防科大、京东和北理工的论文“Deep Model Fusion: A Survey”。 深度模型融合/合并是一种新兴技术&#xff0c;它将多个深度学习模…

.NET CORE程序发布IIS后报错误 500.19

发布IIS后浏览时报错误500.19&#xff0c;同时配置文件web.config的路径中也存在问号“?”。 可能原因&#xff1a;没有安装运行时

CMU 10423 Generative AI:lec14(Vision Language Model:CLIP、VQ-VAE)

文章目录 1 概述2 CLIP (Used in GPT-V)3 VQ-VAE (Used in Gemini)**VQ-VAE 详细笔记****VQ-VAE 的模块组成与数据流** **1. 输入数据****2. 编码器&#xff08;Encoder&#xff09;****2.1 编码器的作用****2.2 数据流与维度变化****2.3 编码器输出** **3. 量化器&#xff08;…

手机使用指南:如何在没有备份的情况下从 Android 设备恢复已删除的联系人

在本指南中&#xff0c;您将了解如何从 Android 手机内存中恢复已删除的联系人。Android 诞生、见证并征服了 80% 的智能手机行业。有些人可能将此称为“非常大胆的宣言”&#xff0c;但最近的统计数据完全支持我们的说法。灵活性、高度改进的可用性和快速性是 Android 操作系统…

Qt QWidget控件

目录 一、概述 二、Qwidget常用属性及函数介绍 2.1 enable 2.2 geometry 2.3 windowTitle 2.4 windowIcon 2.5 cursor 2.6 font 设置字体样式 2.7 toolTip 2.8 focusPolicy焦点策略 2.9 styleSheet 一、概述 widget翻译而来就是小控件&#xff0c;小部件。…

10.3作业

基于TCP的快查云词典 仿照有道云词典功能&#xff0c;实现一个自己的云词典功能&#xff0c;可以查询单词和发音。 服务器描述&#xff1a;服务器启动后&#xff0c;等待客户端连接&#xff0c;完成以下操作&#xff1a; 1.创建用户表、单词表、历史表 2.注册&#xff1a;接…

C++模拟实现vector容器【万字模拟✨】

更多精彩内容..... &#x1f389;❤️播主の主页✨&#x1f618; Stark、-CSDN博客 本文所在专栏&#xff1a; 学习专栏C语言_Stark、的博客-CSDN博客 项目实战C系列_Stark、的博客-CSDN博客 数据结构与算法_Stark、的博客-CSDN博客 座右铭&#xff1a;梦想是一盏明灯&#xff…

mysql-索引笔记

索引 1、什么是索引 索引是对数据库中数据的一种结构化表示。它像一本书的目录&#xff0c;能够快速定位信息&#xff0c;而无需逐行扫描所有数据。 索引的出现其实就是为了提高数据查询的效率&#xff0c;就像书的目录一样。 2、索引的常见模型 2.1.哈希表 用一个哈希函…

828华为云征文|华为云 Flexus X 实例初体验

一直想有自己的一款的服务器&#xff0c;为了更好的进行家庭娱乐&#xff0c;甚至偶尔可以满足个人搭建开发环境的需求&#xff0c;直到接触到了华为云 Flexus X 云服务器。Flexus 云服务器 X 实例是面向中小企业和开发者打造的轻量级云服务器。提供快速应用部署和简易的管理能…

每日论文5—06TCAS2锁相环电流匹配的gain-boosting电荷泵

《Gain-Boosting Charge Pump for Current Matching in Phase-Locked Loop》 06TCAS2 本质上和cascode来增加输出电阻&#xff0c;从而减小电流变化的思路是一样的。这里用了放大器来增加输出电阻。具体做法如下图&#xff1a; 如图1(a)&#xff0c;A3把Vb和Vx拉平&#xff0…

vscode安装及c++配置编译

1、VScode下载 VS Code官网下载地址&#xff1a;Visual Studio Code - Code Editing. Redefined。 2、安装中文插件 搜索chinese&#xff0c;点击install下载安装中文插件。 3、VS Code配置C/C开发环境 3.1、MinGW-w64下载 VS Code是一个高级的编辑器&#xff0c;只能用来写代…

基础算法--枚举

枚举算法是一种简单而有效的算法&#xff0c;它通过枚举所有可能的情况来解决问题。它通常用于解决问题规模比较小的问题&#xff0c;因为它的时间复杂度很高&#xff0c;随着问题的规模增加&#xff0c;算法的效率会急剧下降。 枚举算法的基本思路是通过循环遍历所有可能的情…

Rust和Go谁会更胜一筹

在国内&#xff0c;我认为Go语言会成为未来的主流&#xff0c;因为国内程序员号称码农&#xff0c;比较适合搬砖&#xff0c;而Rust对心智要求太高了&#xff0c;不适合搬砖。 就个人经验来看&#xff0c;Go语言简单&#xff0c;下限低&#xff0c;没有什么心智成本&#xff0c…

使用MTVerseXR SDK实现VR串流

1、概述​ MTVerseXR SDK 是摩尔线程GPU加速的虚拟现实&#xff08;VR&#xff09;流媒体平台&#xff0c;专门用于从远程服务器流式传输基于标准OpenXR的应用程序。MTVerseXR可以通过Wi-Fi和USB流式将VR内容从Windows服务器流式传输到XR客户端设备, 使相对性能低的VR客户端可…