MyBatis3源码深度解析(二十四)级联映射与关联查询(一)级联映射的使用

文章目录

  • 前言
  • 第十章 MyBatis级联映射与懒加载
    • 10.1 MyBatis级联映射的使用
      • 10.1.1 简单查询
        • 10.1.1.1 数据准备
        • 10.1.1.2 编写实体类
        • 10.1.1.3 编写Mapper接口及XML配置文件
        • 10.1.1.4 编写MyBatis主配置文件
        • 10.1.1.5 编写单元测试
      • 10.1.2 一对多级联映射
        • 10.1.2.1 外部Mapper方式
        • 10.1.2.2 JOIN子句方式
      • 10.1.3 一对一关联映射
        • 10.1.3.1 外部Mapper方式
        • 10.1.3.2 JOIN子句方式
      • 10.1.4 Discriminator

前言

MyBatis其中一个比较强大的功能是支持查询结果的级联映射。

使用MyBatis级联映射,可以轻松地实现一对多、一对一、多对多关联查询,甚至实现懒加载。

所谓懒加载,就是当一个实体对象中关联了其他实体对象时,如果没有使用这个被关联的实体对象,则不为被关联的实体对象执行额外的查询操作。而一旦调用当前实体的Getter方法获取被关联的实体对象时,再执行一次额外的查询操作。通过这种方式在一定程度上能够减轻数据库的压力。

第十章 MyBatis级联映射与懒加载

10.1 MyBatis级联映射的使用

10.1.1 简单查询

10.1.1.1 数据准备

假设现在要开发一个电商应用,需要通过数据库记录用户信息和订单信息。用户和订单就是典型的一对多关系,一个用户可以有多个订单,一个订单只会属于一个用户。

为此,在数据库分别新建用户表user和订单表order,并插入一些数据:

CREATE TABLE `user` (`user_id` INT PRIMARY KEY AUTO_INCREMENT,`name` VARCHAR(20),`age` INT,`phone` VARCHAR(20),`birthday` DATETIME
)CREATE TABLE `order`(`order_id` INT PRIMARY KEY AUTO_INCREMENT,`user_id` INT,`order_no` VARCHAR(32),`address` VARCHAR(20),`amount` INT
);insert into `user` (`name`, `age`, `phone`, `birthday`) values(孙悟空','1500','18705464523','0000-01-01 00:00:00');
insert into `user` (`name`, `age`, `phone`, `birthday`) values(猪八戒','1000','15235468789','0500-03-10 00:00:00');insert into `order` (`user_id`, `order_no`, `address`, `amount`) values(1','order_01','广东广州','100');
insert into `order` (`user_id`, `order_no`, `address`, `amount`) values('1','order_02','广东河源','200');
insert into `order` (`user_id`, `order_no`, `address`, `amount`) values(2','order_03','广东佛山','300');

需要注意的是,order是MySQL的关键字,因此建表的时候需要加上反单引号;同时,用户和订单的主键均自动生成。

10.1.1.2 编写实体类

下面编写用户表user和订单表order对应的实体类:

public class User {private Integer userId;private String name;private Integer age;private String phone;private Date birthday;// 用户持有多个订单private List<Order> orderList;// getter setter toString ...
}

User类维护了一个List类型的orderList属性,用于存放用户相关联的订单信息,即一个用户可以对应多笔订单(一对多)。

public class Order {private Integer orderId;private Integer userId;private String orderNo;private String address;private Integer amount;// 一笔订单属于一个用户private User user;// getter setter toString ...
}

Order类维护了一个User属性,用于关联订单对应的用户信息,即一笔订单属于一个用户(一对一)。

10.1.1.3 编写Mapper接口及XML配置文件

下面编写UserMapper接口及其对应的XML配置文件,提供一个getUserById()方法,即根据用户ID查询用户信息:

public interface UserMapper {User getUserById(@Param("userId") Integer userId);
}
<!--UserMapper.xml-->
<mapper namespace="com.star.mybatis.mapper.UserMapper"><select id="getUserById" resultType="User">select * from user where user_id = #{userId}</select>
</mapper>

继续编写OrderMapper接口及其对应的XML配置文件,提供一个listOrderByUserId()方法,即根据用户ID查询订单信息:

public interface OrderMapper {List<Order> listOrderByUserId(@Param("userId") Integer userId);
}
<!--OrderMapper.xml-->
<mapper namespace="com.star.mybatis.mapper.OrderMapper"><select id="listOrderByUserId" resultType="Order">select * from `order` where user_id = #{userId}</select>
</mapper>
10.1.1.4 编写MyBatis主配置文件
<!--mybatis-config.xml-->
<configuration><settings><!--支持返回自动生成主键--><setting name="useGeneratedKeys" value="true"/><!--支持实体名驼峰原则--><setting name="mapUnderscoreToCamelCase" value="true"/><!--日志--><setting name="logImpl" value="STDOUT_LOGGING"/></settings><!--别名处理--><typeAliases><package name="com.star.mybatis.entity"/></typeAliases><!--数据源--><environments default="dev"><environment id="dev"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><!--映射文件--><mappers><mapper resource="mapper/UserMapper.xml"/><mapper resource="mapper/OrderMapper.xml"/></mappers>
</configuration>
10.1.1.5 编写单元测试
public class Test01 {private SqlSession sqlSession;private UserMapper userMapper;private OrderMapper orderMapper;@Beforepublic void init() throws IOException {InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);sqlSession = sqlSessionFactory.openSession();userMapper = sqlSession.getMapper(UserMapper.class);orderMapper = sqlSession.getMapper(OrderMapper.class);}@Testpublic void testSimpleQuery() {User user = userMapper.getUserById(1);System.out.println(user.toString());List<Order> orders = orderMapper.listOrderByUserId(1);orders.forEach(System.out::println);}}

由于本案例会多次使用SqlSession对象、UserMapper对象和OrderMapper对象,因此将这3个对象的初始化使用标注了@Before注解的前置方法来完成,方便单元测试方法直接使用。

执行单元测试testSimpleQuery()方法,控制台打印执行结果:

Opening JDBC Connection
Created connection 1894601438.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@70ed52de]
==>  Preparing: select * from user where user_id = ?
==> Parameters: 1(Integer)
<==    Columns: user_id, name, age, phone, birthday
<==        Row: 1, 孙悟空, 1500, 18705464523, 0001-01-01 00:00:00.0
<==      Total: 1
User{userId=1, name='孙悟空', age=1500, phone='18705464523', birthday=Thu Jan 01 00:00:00 CST 1, orderList=null}
==>  Preparing: select * from `order` where user_id = ?
==> Parameters: 1(Integer)
<==    Columns: order_id, user_id, order_no, address, amount
<==        Row: 1, 1, order_01, 广东广州, 100
<==        Row: 2, 1, order_02, 广东河源, 200
<==      Total: 2
Order{orderId=1, userId=1, orderNo='order_01', address='广东广州', amount=100, user=null}
Order{orderId=2, userId=1, orderNo='order_02', address='广东河源', amount=200, user=null}

由于只是简单的查询操作,所以User对象中的orderList属性为空,Order对象中的user属性为空。

10.1.2 一对多级联映射

简单查询时,User对象中的orderList属性为空。那怎么在查询用户信息的同时,把该用户关联的订单信息也一并查询返回呢?

通过MyBatis的级联映射即可实现这种一对多的级联查询。

10.1.2.1 外部Mapper方式

MyBatis的Mapper配置中提供了一个<collection>标签,用于建立实体间一对多的关系。例如:

<!--UserMapper.xml-->
<resultMap id="fullUser" type="User"><id column="user_id" property="userId"/><result column="name" property="name"/><result column="age" property="age"/><result column="phone" property="phone"/><result column="birthday" property="birthday"/><collection property="orderList"select="com.star.mybatis.mapper.OrderMapper.listOrderByUserId"ofType="Order"javaType="List"column="user_id"></collection>
</resultMap><select id="getFullUserById" resultMap="fullUser">select * from user where user_id = #{userId}
</select>

在上述XML配置中,<collection>标签需要嵌套在<resultMap>标签中使用。它们的属性的作用是:

<resultMap>标签:

  • id:唯一标记一个<resultMap>标签,<select>标签的resultMap属性需要与之相对应。
  • type:指定返回实体的类型是User类。

<collection>标签:

  • property:指定User实体中要填充值的属性是orderList。
  • select:指定通过ID为com.star.mybatis.mapper.OrderMapper.listOrderByUserId的Mapper方法来为User实体的orderList属性填充值。
  • ofType:指定orderList属性中存放的类型是Order。
  • javaType:指定orderList属性的类型是List。
  • column:指定user_id字段作为参数传到listOrderByUserId()方法中。

接下来编写一个单元测试,调用UserMapper接口的getFullUserById()方法:

@Test
public void testOne2ManyQuery() {User user = userMapper.getFullUserById(1);System.out.println(user.toString());
}

控制台打印执行结果:

Opening JDBC Connection
Created connection 1574877131.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5ddeb7cb]
==>  Preparing: select * from user where user_id = ?
==> Parameters: 1(Integer)
<==    Columns: user_id, name, age, phone, birthday
<==        Row: 1, 孙悟空, 1500, 18705464523, 0001-01-01 00:00:00.0
====>  Preparing: select * from `order` where user_id = ?
====> Parameters: 1(Integer)
<====    Columns: order_id, user_id, order_no, address, amount
<====        Row: 1, 1, order_01, 广东广州, 100
<====        Row: 2, 1, order_02, 广东河源, 200
<====      Total: 2
<==      Total: 1
User{userId=1, name='孙悟空', age=1500, phone='18705464523', birthday=Thu Jan 01 00:00:00 CST 1, orderList=[Order{orderId=1, userId=1, orderNo='order_01', address='广东广州', amount=100, user=null}, Order{orderId=2, userId=1, orderNo='order_02', address='广东河源', amount=200, user=null}]}

由执行结果可知,在调用getFullUserById()方法时,MyBatis会先后执行两条SQL语句,第一条查询user表为User实体的属性赋值,第二条执行<collection>标签关联的查询语句为orderList属性赋值。

10.1.2.2 JOIN子句方式

除了使用<collection>标签,还可以使用JOIN子句实现一对多的查询。 例如:

<!--UserMapper.xml-->
<resultMap id="fullUserForJoin" type="User"><id column="user_id" property="userId"/><result column="name" property="name"/><result column="age" property="age"/><result column="phone" property="phone"/><result column="birthday" property="birthday"/><collection property="orderList"ofType="Order"javaType="List"><id property="orderId" column="order_id"/><result property="userId" column="user_id"/><result property="orderNo" column="order_no"/><result property="address" column="address"/><result property="amount" column="amount"/></collection>
</resultMap><select id="getFullUserByIdForJoin" resultMap="fullUserForJoin">select u.*, o.* from user uleft join `order` o on u.user_id = o.user_idwhere u.user_id = #{userId}
</select>

JOIN子句方式与外部Mapper方式不同的地方在于:

第一,JOIN子句方式不需要使用<collection>标签的select属性指定一个外部的Mapper方法为关联属性赋值;

第二,JOIN子句方式的<collection>标签内部,需要为order表的每一个字段设置映射关系,主键使用<id>标签,其他字段使用<result>标签;

接下来编写一个单元测试,调用UserMapper接口的getFullUserByIdForJoin()方法:

@Test
public void testOne2ManyForJoinQuery() {User user = userMapper.getFullUserByIdForJoin(1);System.out.println(user.toString());
}

控制台打印执行结果:

Opening JDBC Connection
Created connection 271800170.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1033576a]
==>  Preparing: select u.*, o.* from user u left join `order` o on u.user_id = o.user_id where u.user_id = ?
==> Parameters: 1(Integer)
<==    Columns: user_id, name, age, phone, birthday, order_id, user_id, order_no, address, amount
<==        Row: 1, 孙悟空, 1500, 18705464523, 0001-01-01 00:00:00.0, 1, 1, order_01, 广东广州, 100
<==        Row: 1, 孙悟空, 1500, 18705464523, 0001-01-01 00:00:00.0, 2, 1, order_02, 广东河源, 200
<==      Total: 2
User{userId=1, name='孙悟空', age=1500, phone='18705464523', birthday=Thu Jan 01 00:00:00 CST 1, orderList=[Order{orderId=1, userId=1, orderNo='order_01', address='广东广州', amount=100, user=null}, Order{orderId=2, userId=1, orderNo='order_02', address='广东河源', amount=200, user=null}]}

由执行结果可知,使用JOIN子句的方式,只会执行一条SQL语句,但仍然可以实现一对多的关联查询。

10.1.3 一对一关联映射

简单查询时,Order对象中的user属性也为空。要在查询Order对象是同时查询出关联的用户信息(一对一),也通过MyBatis的级联映射来实现。

10.1.3.1 外部Mapper方式

一对一级联映射查询跟一对多级联查询类似,不同的是不再使用<collection>标签,而是使用<association>标签。 例如:

<!--OrderMapper.xml-->
<resultMap id="fullOrder" type="Order"><id column="order_id" property="orderId"/><result column="user_id" property="userId"/><result column="order_no" property="orderNo"/><result column="address" property="address"/><result column="amount" property="amount"/><association property="user"select="com.star.mybatis.mapper.UserMapper.getUserById"javaType="User"column="user_id"></association>
</resultMap><select id="getOrderByNo" resultMap="fullOrder">select * from `order` where order_id = #{orderId}
</select>

<association>标签的各个属性和<collection>标签是一样的。

接下来编写一个单元测试,调用OrderMapper接口的getOrderByNo()方法:

@Test
public void testOne2ManyQueryForOrder() {Order order = orderMapper.getOrderByNo(1);System.out.println(order.toString());
}

控制台打印执行结果:

Opening JDBC Connection
Created connection 1574877131.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5ddeb7cb]
==>  Preparing: select * from `order` where order_id = ?
==> Parameters: 1(Integer)
<==    Columns: order_id, user_id, order_no, address, amount
<==        Row: 1, 1, order_01, 广东广州, 100
====>  Preparing: select * from user where user_id = ?
====> Parameters: 1(Integer)
<====    Columns: user_id, name, age, phone, birthday
<====        Row: 1, 孙悟空, 1500, 18705464523, 0001-01-01 00:00:00.0
<====      Total: 1
<==      Total: 1
Order{orderId=1, userId=1, orderNo='order_01', address='广东广州', amount=100, user=User{userId=1, name='孙悟空', age=1500, phone='18705464523', birthday=Thu Jan 01 00:00:00 CST 1, orderList=null}}

由执行结果可知,MyBatis会先后执行两条SQL语句,第一条查询order表为Order实体的属性赋值,第二条执行<association>标签关联的查询语句为user属性赋值。

10.1.3.2 JOIN子句方式

同样,一对一级联查询也可以通过JOIN子句的方式实现。

<!--OrderMapper.xml-->
<resultMap id="fullOrderForJoin" type="Order"><id column="order_id" property="orderId"/><result column="user_id" property="userId"/><result column="order_no" property="orderNo"/><result column="address" property="address"/><result column="amount" property="amount"/><association property="user" javaType="User"><id column="user_id" property="userId"/><result column="name" property="name"/><result column="age" property="age"/><result column="phone" property="phone"/><result column="birthday" property="birthday"/></association>
</resultMap><select id="getOrderByNoForJoin" resultMap="fullOrderForJoin">select o.*, u.* from `order` oleft join user u on o.user_id = u.user_idwhere order_id = #{orderId}
</select>

单元测试代码:

@Test
public void testOne2ManyQueryForOrderForJoin() {Order order = orderMapper.getOrderByNoForJoin(1);System.out.println(order.toString());
}

控制台打印执行结果:

Opening JDBC Connection
Created connection 1574877131.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5ddeb7cb]
==>  Preparing: select o.*, u.* from `order` o left join user u on o.user_id = u.user_id where order_id = ?
==> Parameters: 1(Integer)
<==    Columns: order_id, user_id, order_no, address, amount, user_id, name, age, phone, birthday
<==        Row: 1, 1, order_01, 广东广州, 100, 1, 孙悟空, 1500, 18705464523, 0001-01-01 00:00:00.0
<==      Total: 1
Order{orderId=1, userId=1, orderNo='order_01', address='广东广州', amount=100, user=User{userId=1, name='孙悟空', age=1500, phone='18705464523', birthday=Thu Jan 01 00:00:00 CST 1, orderList=null}}

由执行结果可知,使用JOIN子句的方式,只会执行一条SQL语句,但仍然可以实现一对一的关联查询。

10.1.4 Discriminator

在MyBatis的级联映射中还有一个比较重要的概念:Discriminator,意思是“鉴别器”,它类似于Java中的switch语法,能够根据数据库记录中某个字段的值映射到不同的ResultMap。

假设现在有这样一个需求:当查询用户信息时,如果用户年龄为1000岁(目前数据库中孙悟空1500岁,猪八戒1000岁),则查询用户信息,否则不查询。

即根据user表中的age字段的值不同,做不同的映射处理,则可以使用<discriminator>标签来完成。例如:

<!--UserMapper.xml-->
<resultMap id="fullUserForDis" type="User"><id property="userId" column="user_id"/><result column="name" property="name"/><result column="age" property="age"/><result column="phone" property="phone"/><result column="birthday" property="birthday"/><!--判断age字段--><discriminator javaType="Integer" column="age"><case value="1000" resultType="User"><collection property="orderList"select="com.star.mybatis.mapper.OrderMapper.listOrderByUserId"ofType="Order"javaType="List"column="user_id"><id property="orderId" column="order_id"/><result property="userId" column="user_id"/><result property="orderNo" column="order_no"/><result property="address" column="address"/><result property="amount" column="amount"/></collection></case></discriminator>
</resultMap><select id="getFullUserByIdForDis" resultMap="fullUserForDis">select * from user where user_id = #{userId}
</select>

如上面的配置所示,使用<discriminator>标签对user表的age字段进行映射。当age字段值为1000时,为User实体的orderList属性关联一个外部的查询Mapper;当age字段值不为1000时,则不做映射处理。

单元测试代码:

@Test
public void testDiscriminator() {User user1 = userMapper.getFullUserByIdForDis(1);System.out.println(user1.toString());System.out.println("-------111----------");User user2 = userMapper.getFullUserByIdForDis(2);System.out.println(user2.toString());System.out.println("--------222---------");
}

控制台打印执行结果:

Opening JDBC Connection
Created connection 271800170.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1033576a]
==>  Preparing: select * from user where user_id = ?
==> Parameters: 1(Integer)
<==    Columns: user_id, name, age, phone, birthday
<==        Row: 1, 孙悟空, 1500, 18705464523, 0001-01-01 00:00:00.0
<==      Total: 1
User{userId=1, name='孙悟空', age=1500, phone='18705464523', birthday=Thu Jan 01 00:00:00 CST 1, orderList=null}
-------111----------
==>  Preparing: select * from user where user_id = ?
==> Parameters: 2(Integer)
<==    Columns: user_id, name, age, phone, birthday
<==        Row: 2, 猪八戒, 1000, 15235468789, 0500-03-10 00:00:00.0
====>  Preparing: select * from `order` where user_id = ?
====> Parameters: 2(Integer)
<====    Columns: order_id, user_id, order_no, address, amount
<====        Row: 3, 2, order_03, 广东佛山, 300
<====      Total: 1
<==      Total: 1
User{userId=2, name='猪八戒', age=1000, phone='15235468789', birthday=Fri Mar 10 00:00:00 CST 500, orderList=[Order{orderId=3, userId=2, orderNo='order_03', address='广东佛山', amount=300, user=null}]}
--------222---------

由结果可知,第一次查询由于age字段值为1500,所以没有继续查询关联的order表;第二次查询由于age字段值为1000,触发关联查询order表。

······

本节完,更多内容请查阅分类专栏:MyBatis3源码深度解析

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

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

相关文章

怎麼實現Nginx反向代理?

Nginx是一款開源軟體&#xff0c;可以作為Web伺服器、負載均衡器和反向代理使用&#xff0c;是高性能的HTTP和反向代理伺服器。其中反向代理是Nginx的一項重要特性。接下來&#xff0c;我們詳細講一下Nginx反向代理的實現和應用。 反向代理是什麼&#xff1f; 代理一詞通常指的…

使用第三方远程连接工具ssh连接vagrant创建的虚拟机

vagrant默认密码都是vagrant 密码认证默认是关闭的&#xff0c;进入虚拟机&#xff0c;打开密码认证 1、使用命令vi /etc/ssh/sshd_config进入配置&#xff0c;注意要切换到root用户&#xff0c;这个配置root有权限 2、找到PasswordAuthentication默认为no,改为yes 3、重启虚…

Redis如何应对缓存穿透问题——Java全栈知识(9)

我们在正常使用缓存的时候的流程大概就是这样的&#xff1a; 请求访问缓存&#xff0c;缓存有数据就返回&#xff0c;缓存无数据就去数据库里面查数据写入到缓存中。 1、缓存穿透问题 但是如果由恶意请求&#xff0c;短时间内大量的访问不存在的数据&#xff0c;这时每个请求…

暴力破解笔记

1 暴力破解简介 暴力破解&#xff1a; 蛮力攻击&#xff0c;又称为穷举攻击&#xff0c;或暴力破解&#xff0c;将密码进行逐个尝试验证&#xff0c;直到尝试出真正的密码为止。 暴力破解是指采用反复试错的方法并希望最终猜对&#xff0c;以尝试破解密码或用户名或找到隐藏的…

33岁TVB「御用少妻」近况曝光,中戏毕业后跑龙套8年终于上位。

日前&#xff0c;33岁无线小花刘温馨应邀出席了「香港首个女性健康运动与艺术文化慈善嘉年华」&#xff0c;并开心写道&#xff1a;「好开心参与到&#xff5e;香港首个女性健康运动与艺术文化慈善嘉年华 H.E.R Festival。片一&#xff1a;请找亮点。」片中刘温馨暂时其柔软的身…

3.26学习总结

java 实例变量和局部变量 实例变量是记录这个类中对象的特点的每一个对象的实例变量都可以不同(例如名字,性别等),其中一个对象的实例变量改变不会影响其他的变量. 类变量是一种特殊的实例变量,他的特殊在于所有的对象的类变量都是相同的,当一个对象改变了类变量那么所有对象…

雷卯推荐多种系列汽车级TVS供您选择

1. 车规级TVS的应用 2.车规级TVS系列表格如下 3.方案推荐 12V汽车电源浪涌保护方案 方案优点&#xff1a;用于满足前装汽车的ISO7637-2 5A5BA测试&#xff0c;可采用单独大功率的TVS或PTCTVS的组合方案&#xff0c;满足ISO10605-2&#xff0c; 等级4&#xff0c;接触放电15K…

初识云原生、虚拟化、DevOps

文章目录 K8S虚拟化DevOpsdevops平台搭建工具大数据架构 K8S master 主节点&#xff0c;控制平台&#xff0c;Master节点负责核心的调度、管理和运维&#xff0c;不需要很高性能&#xff0c;不跑任务&#xff0c;通常一个就行了&#xff0c;也可以开多个主节点来提高集群可用度…

uniapp 使用命令行创建vue3 ts 项目

命令行创建 uni-app 项目&#xff1a; vue3 ts 版 npx degit dcloudio/uni-preset-vue#vite-ts 项目名称注意 Vue3/Vite版要求 node 版本^14.18.0 || >16.0.0 如果下载失败&#xff0c;请去gitee下载 https://gitee.com/dcloud/uni-preset-vue/repository/archive/vite-ts…

2024 解决 Failed to launch process [ElasticSearch]

操作系统&#xff1a;centos 7 (x86) sonarQube不能使⽤root账号进⾏启动&#xff0c;所以需要创建普通⽤户及其⽤户组 一、问题描述&#xff1a;使用root启动时&#xff0c;一直反馈 SonarQube is not running 问题原因&#xff1a;不能够使用root用户进行启动 解决方案…

【Effective Web】html/css优化和技巧

html/css优化和技巧 html/css可以做到一些js的功能&#xff0c;减少js操作dom的高昂成本。 巧用伪类 显示勾选时文案 checkbo勾选时触发&#xff0c;实现checkbox的简单选中事件处理 <template><input type"checkbox" /><span class"checkb…

Unity Text文本固定框条内无缝衔接循环滚动效果实现

在Unity中要实现在一个固定背景框条内播放文本&#xff0c;并且文本能够衔接循环滚动&#xff0c;可以通过以下步骤实现&#xff1a; 1、创建一个Image组件作为背景框条&#xff0c;在Image下添加一个Mask组件&#xff0c;如下图&#xff1a; 2、创建Text文本组件&#xff0c…

深入理解TCP/IP协议:网络通信的基石

提示&#xff1a;本系列文章重点学习TCP/IP协议 深入理解TCP/IP协议&#xff1a;网络通信的基石 简介一、TCP/IP协议的基本原理二、TCP/IP协议的工作机制三、TCP面向连接建立连接&#xff1a;断开连接&#xff1a; 四、分层传输五、TCP流量控制滑动窗口机制流量控制的工作流程优…

深入解析代理模式:使用场景、实现及应用实例

在软件设计中&#xff0c;代理模式是一种常用的设计模式&#xff0c;它为其他对象提供一种代理以控制对这个对象的访问。代理模式在多种场景下都能发挥重要作用&#xff0c;特别是在需要控制对象访问权限、降低系统耦合度或提高系统性能时。 一、代理模式的使用条件 代理模式…

ABAP - 上传文件模板到SMW0,并从SMW0上下载模板

upload file template to SMW0 and download the template from it 首先上传文件到tcode SMW0 选择新建后,输入文件名和描述,再选择想要上传的文件 上传完成后: 在表WWWPARAMS, WWWDATA里就会有信息存进去 然后就可以程序里写代码了: 屏幕上的效果:

iOS - Runtime - Class的结构

文章目录 iOS - Runtime - Class的结构前言1. Class的结构1.1 Class的结构1.1.1 objc_class1.1.2 class_rw_t1.1.3 class_ro_t 1.2 class_rw_t和class_ro_t的区别1.3 class_rw_t和class_ro_t的关系1.3.1 分析关系1.3.2 原因 1.4 method_t1.4.1 Type Encoding1.4.2 types iOS - …

langchain调用语言模型chatglm4从智谱AI

目录 ​0.langchain agent 原理 ReAct 1.langchain agent使用chatgpt调用tools的源代码 2.自定义本地语言模型的代码 3.其他加速方法 背景&#xff1a;如果使用openai的chatgpt4进行语言问答&#xff0c;是需要从国内到国外的一个客户请求-->openai服务器response的一个…

pytorch反向传播算法

目录 1. 链式法则复习2. 多输出感知机3. 多层感知机4. 多层感知机梯度推导5. 反向传播的总结 1. 链式法则复习 2. 多输出感知机 3. 多层感知机 如图&#xff1a; 4. 多层感知机梯度推导 简化式子把( O k O_k Ok​ - t k t_k tk​) O k O_k Ok​(1 - O k O_k Ok​)起个别名…

react native上传二进制图片、视频的方法

react native获取本地图片我用的react-native-image-picker&#xff0c;但是它只能获取图片路径&#xff0c;以及base64的图片&#xff0c;不能获取到binary二进制形式的。 一开始我是让后端改造接口&#xff0c;把原本传binary的改成了base64&#xff0c;可是&#xff0c;躲得…

[自研开源] 数据集成之分批传输 v0.7

开源地址&#xff1a;gitee | github 详细介绍&#xff1a;MyData 基于 Web API 的数据集成平台 部署文档&#xff1a;用 Docker 部署 MyData 使用手册&#xff1a;MyData 使用手册 试用体验&#xff1a;https://demo.mydata.work 交流Q群&#xff1a;430089673 介绍 本篇基于…