07.MyBatis映射器:一对一关联查询

大家好,我是王有志,一个分享硬核 Java 技术的金融摸鱼侠,欢迎大家加入 Java 人自己的交流群“共同富裕的 Java 人”。

《MyBatis 映射器:实现简单的 SQL 语句》中,我们在 MyBatis 映射器的查询语句中使用 resultType 元素实现了从数据库到 Java 对象的自动映射,但是这种自动映射是有它的局限性的,首先是要求数据库中表的列名必须与 Java 对象中的字段名保持一致,其次是无法实现关联查询,也就是说使用 resultType 元素无法应对一些复杂的场景,那么对于复杂的查询场景,MyBatis 中有没有可以应对的方案呢?
答案是肯定的,MyBatis 对这些复杂场景给出了自己的答案:resultMap 元素。

前期准备工作

正式开始前,我们要做一些准备工作,主要是两部分:数据库准备和项目准备。

数据库准备

在本文及未来的《MyBatis 映射器:一对多关联查询》的中,我们需要使用一套简单的“用户-订单”体系,数据库结构如下:

这里简单的描述下这 4 张表之间的关系:

  • 用户表(user)与用户订单表(user_order)之间通过 user_id 进行关联,每个用户可以对应多个订单,即一对多;
  • 用户订单表(user_order)与订单明细表(order_item)之间通过 order_id 进行关联,每个订单可以对应多个商品,即一对多;
  • 用户订单表(user_order)与支付订单表(pay_order)之间通过 order_id 进行关联,每个订单对应一个支付订单,即一对一。

你不需要照着图片创建这些表,因为我在文章的末尾准备了这 4 张表的建表 SQL 语句和测试数据的初始化 SQL 语句。

项目准备

我们再来准备一个用于练习的 MyBatis 项目,Maven 依赖和 mybatis-config.xml 的配置你可以在《MyBatis入门》中找到,这里我就不再赘述了。
接着,我们为上面的 4 张表创建对应的 Java 对象,Mapper 接口和映射器文件。如果你熟悉 MyBatis 生成工具(如 MyBatis-Generator,MyBatis X 等),你可以使用生成工具来创建这些文件,如果你不熟悉,你可以直接创建这些文件,只需要照着数据库表创建 Java 对象,并且创建对应的空的 Mapper 接口和映射器文件就可以了。
最后,我们准备一个单元测试文件,只需要提前做一些配置工作就可以了,代码如下:

public class CustomizeMappedTest {

  private static SqlSession sqlSession;

  private static UserMapper userMapper;

  private static UserOrderMapper userOrderMapper;

  private static PayOrderMapper payOrderMapper;

  private static OrderItemMapper orderItemMapper;

  @BeforeClass
  public static void init() throws IOException {
    Reader mysqlReader = Resources.getResourceAsReader("mybatis-config.xml");
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(mysqlReader);
    sqlSession = sqlSessionFactory.openSession();

    userMapper = sqlSession.getMapper(UserMapper.class);
    userOrderMapper = sqlSession.getMapper(UserOrderMapper.class);
    payOrderMapper = sqlSession.getMapper(PayOrderMapper.class);
    orderItemMapper = sqlSession.getMapper(OrderItemMapper.class);
  }
}

至此,我们已经完成了所有前期准备工作,来看一下工程的整体结构:

基础用法:定义映射规则

如果你是通过 MyBatis 生成工具创建的映射器文件,那么在你的映射器文件中会出现如下配置(如果不是的话,把这些 copy 到你的项目中),这里以 UserOrderMapper.xml 为例:

<resultMap id="BaseResultMap" type="com.wyz.entity.UserOrderDO">
  <id property="orderId" column="order_id" jdbcType="INTEGER"/>
  <result property="userId" column="user_id" jdbcType="INTEGER"/>
  <result property="orderNo" column="order_no" jdbcType="VARCHAR"/>
  <result property="orderPrice" column="order_price" jdbcType="DECIMAL"/>
  <result property="orderStatus" column="order_status" jdbcType="INTEGER"/>
  <result property="createDate" column="create_date" jdbcType="DATE"/>
  <result property="payDate" column="pay_date" jdbcType="DATE"/>
</resultMap>

这便是 resultMap 元素最基础的用法,指定数据库表中字段与 Java 对象中字段的映射关系,定义数据库表与 Java 对象的映射规则
上面的配置内容并不难理解,这里我做一个简单的解释:

  • resultMap 元素:用于自定义映射规则;
    • id 属性,定义了 resultMap 元素的唯一标识;
    • type 属性,定义了与 resultMap 元素对应的 Java 对象;
  • id 元素:定义了数据库中主键与 Java 对象中字段的映射关系;
    • property 属性:映射到 Java 对象中的字段名;
    • column 属性:数据库表中的字段名;
    • jdbcType 属性:声明了数据库表中字段的类型;
  • result 元素,定义了数据库中普通字段与 Java 对象中字段的映射关系。

id 元素与 result 元素所使用的属性完全相同, 除了上面的 3 个之外,还有 javaType 属性和 typeHandler 属性,分别用于声明 Java 对象中字段的类型和字段需要使用的类型处理器
注意,由于使用 resultMap 元素是将数据库表中的字段名与 Java 对象中的字段名建立映射关系,因此我们不需要考虑到数据库字段命名规范与 Java 对象字段命名规范间的差异,也不需要在 mybatis-config.xml 中配置插件“mapUnderscoreToCamelCase”。
假设此时,老板提出了一个需求:“我想要通过订单号查询出订单信息”,那么我们可以这样定义 Mapper 接口中的方法:

UserOrderDO selectByOrderNo(@Param("orderNo")String orderNo);

映射器中的 SQL 语句如下:

<select id="selectByOrderNo" resultMap="BaseResultMap">
  select * from user_order where order_no = #{orderNo, jdbcType=VARCHAR}
</select>

最后我们来写单元测试:

@Test
public void selectByOrderNo() {
  UserOrderDO userOrder = userOrderMapper.selectByOrderNo("D202405082208045788");
  System.out.println("查询结果:");
  System.out.println(JSON.toJSONString(userOrder, JSONWriter.Feature.PrettyFormat));
}

执行单元测试,我们来看控制台输出的结果:

可以看到,测试结果符合我们的预期,数据库中表的字段与 Java 对象中的字段完成了映射。
当然,如果 resultMap 元素只有上面的那点功能的话,我们完全没有必要学习它。resultMap 元素最强大的功能在于它能够帮助我们实现关联查询,无论是一对一关联还是一对多关联,resultMap 都提供了解决方案

进阶用法:使用 association 元素实现一对一关联查询

完成了查询订单信息的功能后,老板提出了新的要求:“我想要用订单号同时查询出订单信息和支付订单信息”。
最容易想到的办法是拆分成多步查询,首先用订单号查询出订单信息,再用订单 ID 去查询关联的支付订单信息,最后将两者的数据合并后输出,但是这么做的问题是,两次查询需要经历两次数据库交互,会带来额外的性能损耗。
如果想要通过一次数据库交互查询出两张表的数据,可以使用联表查询一次性将用户订单与支付订单的数据全部查询出来,SQL 语句如下:

select uo.order_id,
       uo.user_id,
       uo.order_no,
       uo.order_price,
       uo.order_status,
       uo.create_date,
       uo.pay_date,
       po.pay_order_id as po_pay_order_id,
       po.order_id     as po_order_id,
       po.pay_order_no as po_pay_order_no,
       po.pay_amount   as po_pay_amount,
       po.pay_channel  as po_pay_channel,
       po.pay_status   as po_pay_status,
       po.create_date  as po_create_date,
       po.finish_date  as po_finish_date
from user_order uo,
     pay_order po
where uo.order_no = 'D202405082208045788'
  and uo.order_id = po.order_id;

在 SQL 语句的查询字段中,我为所有 pay_order 表的字段添加了前缀“po_”,这是因为 user_order 表与 pay_order 表有重名字段 order_id 和 create_date,虽然两张表中的 order_id 字段含义相同,取值也一样,但是 create_date 字段的含义却不相同,为了起到区分的作用,索性为 pay_order 表的所有字段都起了别名。
那么对于这样的查询结果我们该怎样使用 resultMap 元素进行映射呢?答案是使用 resultMap 元素和它的子元素 association 来实现一对一联表查询的结果集映射
我们先来修改下 UserOrderDO 对象,代码非常简单,只需要将 PayOrderDO 对象组合进来就行,如下:

public class UserOrderDO   {
  // 省略 UserOrderDO 本身的字段

  /**
   * 支付订单信息
   */
  private PayOrderDO payOrder;
}

接着我们使用 resultMap 元素来构建新的映射规则“userOrderContainPayOrderMap”:

<resultMap id="userOrderContainPayOrderMap" type="com.wyz.entity.UserOrderDO" extends="BaseResultMap">
  <association property="payOrder" javaType="com.wyz.entity.PayOrderDO" columnPrefix="po_">
    <id property="payOrderId" column="pay_order_id" jdbcType="INTEGER"/>
    <result property="orderId" column="order_id" jdbcType="INTEGER"/>
    <result property="payOrderNo" column="pay_order_no" jdbcType="VARCHAR"/>
    <result property="payAmount" column="pay_amount" jdbcType="DECIMAL"/>
    <result property="payChannel" column="pay_channel" jdbcType="INTEGER"/>
    <result property="payStatus" column="pay_status" jdbcType="INTEGER"/>
    <result property="createDate" column="create_date" jdbcType="DATE"/>
    <result property="finishDate" column="finish_date" jdbcType="DATE"/>
  </association>
</resultMap>

我们来解释下“userOrderContainPayOrderMap”的配置。
首先是 resultMap 元素中出现的 extends 属性,resultMap 元素中的 extends 属性与 Java 中的关键字 extends 的作用是一样的,用于继承父类(映射规则)。
接着是 association 元素,association 元素表示一个复杂 Java 对象的关联,我们来逐一解释 association 元素中出现的属性:

  • property 属性,用于配置该类型在 Java 对象中字段名,在我们的例子中,即 PayOrderDO 对象在 UserOrderDO 对象中的字段名;
  • javaType 属性,用于生命 association 元素关联的 Java 对象类型
  • columnPrefix 属性,用于配置数据库查询字段的前缀,使用 columnPrefix 属性后,association 元素中配置的字段可以省略前缀,即 SQL 语句中使用了别名“po_pay_order_id”,在配置时可以直接使用“pay_order_id”。

接着我们来定义 Mapper 接口中的方法:

UserOrderDO selectUserOrderAndPayOrderByOrderNo(@Param("orderNo")String orderNo);

然后是编写映射器中对应的 SQL 语句:

<select id="selectUserOrderAndPayOrderByOrderNo" resultMap="userOrderContainPayOrderMap">
  select uo.order_id,
    uo.user_id,
    uo.order_no,
    uo.order_price,
    uo.order_status,
    uo.create_date,
    uo.pay_date,
    po.pay_order_id as po_pay_order_id,
    po.order_id     as po_order_id,
    po.pay_order_no as po_pay_order_no,
    po.pay_amount   as po_pay_amount,
    po.pay_channel  as po_pay_channel,
    po.pay_status   as po_pay_status,
    po.create_date  as po_create_date,
    po.finish_date  as po_finish_date
    from user_order uo,
    pay_order po
  where uo.order_no = #{orderNo,jdbcType=VARCHAR}
    and uo.order_id = po.order_id;
</select>

最后我们来写单元测试:

public void selectUserOrderAndPayOrderByOrderNo() {
  UserOrderDO userOrder = userOrderMapper.selectUserOrderAndPayOrderByOrderNo("D202405082208045788");
  System.out.println("查询结果:");
  System.out.println(JSON.toJSONString(userOrder, JSONWriter.Feature.PrettyFormat));
}

执行单元测试,我们来看控制台输出的内容:

可以看到,控制台输出的结果中,联表查询的结果能够正常的映射到 UserOrderDO 对象中组合的 PayOrderDO 对象上。

进阶用法:使用 association 元素实现嵌套查询

最后我们来看一种使用 association 元素实现嵌套查询的方法。
association 元素可以使用简单的 SQL 语句进行嵌套查询,这与我们最开始想到的分步查询,组合结果的想法是一样的。
首先我们定义嵌套查询的 Mapper 接口中的方法:

UserOrderDO selectUserOrderAndPayOrderByOrderNoNest(@Param("orderNo")String orderNo);

Tips:千万不要诟病我起的方法名啊~~
接着我们来写映射器文件中对应的 SQL 语句:

<select id="selectUserOrderAndPayOrderByOrderNoNest" resultMap="userOrderContainPayOrderNestMap">
  select order_id,
         user_id,
         order_no,
         order_price,
         order_status,
         create_date,
         pay_date
  from user_order
  where order_no = #{orderNo,jdbcType=VARCHAR}
</select>

注意看,这里的 SQL 语句中只是很简单的 user_order 表的单表查询,那么我是如何将 pay_order 表中的数据填充到 UserOrderDO 对象中的呢?
这里我们要先为 PayOrderMapper 补充一个非常简单的接口方法,如下:

PayOrderDO selectPayOrderByOrderId(@Param("orderId") Integer orderId);

接着来完善对应的映射器文件内容,如下:

<resultMap id="BaseResultMap" type="com.wyz.entity.PayOrderDO">
  <id property="payOrderId" column="pay_order_id" jdbcType="INTEGER"/>
  <result property="orderId" column="order_id" jdbcType="INTEGER"/>
  <result property="payOrderNo" column="pay_order_no" jdbcType="VARCHAR"/>
  <result property="payAmount" column="pay_amount" jdbcType="DECIMAL"/>
  <result property="payChannel" column="pay_channel" jdbcType="INTEGER"/>
  <result property="payStatus" column="pay_status" jdbcType="INTEGER"/>
  <result property="createDate" column="create_date" jdbcType="DATE"/>
  <result property="finishDate" column="finish_date" jdbcType="DATE"/>
</resultMap>

<select id="selectPayOrderByOrderId" resultMap="BaseResultMap">
  select * from pay_order where order_id = #{orderId,jdbcType=INTEGER}
</select>

注意,因为没有开启插件“mapUnderscoreToCamelCase”,所以自动映射无法完成下划线与驼峰命名法的转换,所以这里也使用了 resultMap 进行映射。
做完了这些准备工作后,我们在 UserOrderMappe.xml 定义新的映射规则“userOrderContainPayOrderNestMap”,如下:

<resultMap id="userOrderContainPayOrderNestMap" type="com.wyz.entity.UserOrderDO" extends="BaseResultMap">
  <association 
    property="payOrder" 
    javaType="com.wyz.entity.PayOrderDO" 
    select="com.wyz.mapper.PayOrderMapper.selectPayOrderByOrderId"
    column="{orderId=order_id}" />
</resultMap>

来解释下这里 association 元素中出现的两个陌生属性:

  • select 属性,用于配置嵌套查询的 SQL 语句,在这个例子中就是使用订单 id 查询支付订单信息的 SQL 语句;
  • column 属性,配置查询语句中所用到的参数,即PayOrderMapper#selectPayOrderByOrderId方法中使用的参数,如果有多个参数的话使用英文逗号分隔,例如:{orderId=order_id, payOrderId=pay_order_id}

最后我们编写单元测试代码:

public void selectUserOrderAndPayOrderByOrderNoNest() {
  UserOrderDO userOrder = userOrderMapper.selectUserOrderAndPayOrderByOrderNoNest("D202405082208045788");
  System.out.println("查询结果:");
  System.out.println(JSON.toJSONString(userOrder, JSONWriter.Feature.PrettyFormat));
}

执行单元测试后,我们来观察控制台的数据结果:

先来看控制台最后输出的查询结果,依旧符合我们的预期,接着来看 MyBatis 打印的 SQL 语句日志,可以看到这里执行了两条 SQL 语句,分别是通过订单号查询用户订单信息的 SQL 语句和通过用户订单 Id 查询支付订单信息的 SQL 语句,这说明在 association 元素中使用嵌套查询,执行了两次 SQL 语句。

附录:SQL 语句

用户表

建表语句:

create table user (
  user_id   int         not null comment '用户Id' primary key,
  name      varchar(50) not null comment '用户名',
  age       int         not null comment '年龄',
  gender    varchar(50) not null comment '性别',
  id_type   int         not null comment '证件类型',
  id_number varchar(50) not null comment '证件号'
) comment '用户表';

初始化语句:

INSERT INTO mybatis.user (user_id, name, age, gender, id_type, id_number)
VALUES (1, '刘一', 17, 'M', 1, '1101012000808186530');

用户订单表

建表语句:

create table user_order (
  order_id     int auto_increment comment '订单表主键' primary key,
  user_id      int            not null comment 'user表的主键',
  order_no     varchar(50)    null comment '订单号',
  order_price  decimal(18, 2) not null comment '订单价格',
  order_status int            null comment '订单状态',
  create_date  date           null comment '订单创建时间',
  pay_date     date           null comment '订单支付时间'
) comment '用户订单表';

初始化语句:

INSERT INTO user_order (order_id, user_id, order_no, order_price, order_status, create_date, pay_date)
VALUES (1, 1, 'D202405082208045788', 10000.00, 1, '2024-05-14', '2024-05-14');

INSERT INTO user_order (order_id, user_id, order_no, order_price, order_status, create_date, pay_date) 
VALUES (2, 1, 'D202405131542336954', 9900.00, 1, '2024-05-01', '2024-05-01');

订单明细表

建表语句:

create table order_item (
  item_id         int            not null comment '订单商品表主键' primary key,
  order_id        int            null comment '订单表主键',
  commodity_id    int            null comment '商品表主键',
  commodity_price decimal(18, 2) null comment '商品价格',
  commodity_count int            null comment '商品数量'
) comment '订单明细表';

初始化语句:

INSERT INTO order_item (item_id, order_id, commodity_id, commodity_price, commodity_count)
VALUES (1, 1, 350071, 100.00, 10);

INSERT INTO order_item (item_id, order_id, commodity_id, commodity_price, commodity_count)
VALUES (2, 1, 350083, 500.00, 10);

INSERT INTO order_item (item_id, order_id, commodity_id, commodity_price, commodity_count)
VALUES (3, 1, 360302, 400.00, 10);

支付订单表

建表语句:

create table pay_order (
  pay_order_id int            not null comment '支付订单表主键' primary key,
  order_id     int            null comment '订单表主键',
  pay_order_no varchar(50)    null comment '支付订单号',
  pay_amount   decimal(18, 2) null comment '支付金额',
  pay_channel  int            null comment '支付渠道',
  pay_status   int            null comment '支付状态',
  create_date  date           null comment '支付订单创建时间',
  finish_date  date           null comment '支付订单完成时间'
) comment '支付订单表';

初始化语句:

INSERT INTO pay_order (pay_order_id, order_id, pay_order_no, pay_amount, pay_channel, pay_status, create_date, finish_date) 
VALUES (1, 1, 'Z202405082208557945', 10000.00, 37, 1, '2024-05-15', '2024-05-15');

INSERT INTO pay_order (pay_order_id, order_id, pay_order_no, pay_amount, pay_channel, pay_status, create_date, finish_date) 
VALUES (2, 2, 'Z202405131543079921', 9900.00, 98, 1, '2024-05-01', '2024-05-01');

附录:数据库别名的“骚”操作

使用数据库别名实现自动映射

实际上,使用数据库别名也可以在不使用插件“mapUnderscoreToCamelCase”时,实现自动映射,例如:

<select id="selectByOrderNoUseAlias" resultType="com.wyz.entity.UserOrderDO">
  select order_id as orderId,
         user_id as userId,
         order_no as orderNo,
         order_price as orderPrice,
         order_status as orderStatus,
         create_date as createDate,
         pay_date as payDate
  from user_order
  where order_no = #{orderNo,jdbcType=VARCHAR}
</select>

使用数据库表名实现一对一关联自动映射

前面我们借助了 resultMap 元素和其子元素 association 实现了一对一关联映射,但实际上,这种场景我们依旧可以借助数据库别名来实现自动映射。
先来写一个 Mapper 接口:

UserOrderDO selectUserOrderAndPayOrderByOrderNoUseAlias(@Param("orderNo")String orderNo);

接着我们来写映射器文件中的 SQL 语句:

<select id="selectUserOrderAndPayOrderByOrderNoUseAlias" resultType="com.wyz.entity.UserOrderDO">
  select uo.order_id     as orderId,
         uo.user_id      as userId,
         uo.order_no     as orderNo,
         uo.order_price  as orderPrice,
         uo.order_status as orderStatus,
         uo.create_date  as createDate,
         uo.pay_date     as payDate,
         po.pay_order_id as "payOrder.payOrderId",
         po.order_id     as "payOrder.orderId",
         po.pay_order_no as "payOrder.payOrderNo",
         po.pay_amount   as "payOrder.payAmount",
         po.pay_channel  as "payOrder.payChannel",
         po.pay_status   as "payOrder.payStatus",
         po.create_date  as "payOrder.createDate",
         po.finish_date  as "payOrder.finishDate"
  from user_order uo, pay_order po
  where uo.order_no = #{orderNo,jdbcType=VARCHAR}
    and uo.order_id = po.order_id
</select>

最后你可以写一个单元测试来测试下结果。


尾图(二维码).png

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

面向对象复习(java)

文章目录 包在本地 cmd 编译包规则import(导包&#xff09; thisthis 访问实例方法this 访问构造方法 supersuper 访问父类构造器super访问父类方法super 访问父类属性 构造方法访问权限封装继承细节方法重写(覆盖)子父类同名变量问题关于子父类方法的继承问题 多态向上转型和向…

创新入门 | 病毒循环Viral Loop是什么?为何能实现指数增长

今天&#xff0c;很多高速增长的成功创业公司都在采用”病毒循环“的策略去快速传播、并扩大用户基础。究竟什么是“病毒循环”&#xff1f;初创公司的创始人为何需要重视这个策略&#xff1f;这篇文章中将会一一解答与病毒循环有关的各种问题。 一、什么是病毒循环&#xff08…

NV-Embed论文阅读笔记

这是NVIDIA的一篇论文&#xff0c;LLM通常使用的是GPT的decoder范式作为一个生成模型&#xff0c;文章探讨如何利用这样的decoder生成模型来实现BERT这样的encoder的功能&#xff0c;即提取有效的embedding。现有的方法提取embedding的方式无非是 1 mean pooling&#xff1b; 2…

算法竞赛数论杂题

menji 和 gcd 题目&#xff1a; 一开始以为是只有l不确定&#xff0c;r是确定的&#xff0c;这样的话我们可以枚举r的所有约数&#xff0c;然后对其每个约数x进行判断&#xff0c;判断是否满足题意&#xff0c;具体做法是先让l % x如果 0则该约数可行&#xff0c;如果不可行…

蚓链数字化生态平台,开启企业未来新篇章!

在如今数字化浪潮势不可挡的时代&#xff0c;企业发展可谓是机遇与挑战并存&#xff01;而蚓链数字化生态平台系统的出现&#xff0c;绝非是给企业一套平平无奇的营销方案或工具那么简单。 它赋予企业的&#xff0c;是在产业生态链中获取海量数据价值的关键且强大的能力&#x…

嵌入式linux系统中SPI子系统验证03

今天主要给大家分享一下&#xff0c;如何使用SPI总线进行验证的方法。 第一&#xff1a;SPI验证流程 1. echo 1 > /dev / spidev3.0 2&#xff0e;逻辑分析仪抓波形 3.十六进指转化为十进制 4.ASCII字符代码表匹配 第二&#xff1a;SPI验证结果 第三&#xff1a;设备…

kotlin函数

1、函数定义 // 下边定义了main函数 fun main() {} 2、函数的类型 // foo函数定义 fun foo () {} // 对应无参类型 () -> Unit fun foo (a: Int):String {} // 对应有参类型 (Int) -> String 3、函数的引用 函数的引用类似C语言中的函数指针&#xff0c;可用于函数传…

鸿蒙HarmonyOS实战:渲染控制、路由案例

条件渲染 简单来说&#xff0c;就是动态控制组件的显示与隐藏&#xff0c;类似于vue中的v-if 但是这里写法就是用if、else、else if看起来更像是原生的感觉 效果 循环渲染 我们实际开发中&#xff0c;数据一般是后端返回来的对象格式&#xff0c;对此我们需要进行遍历&#…

图解Linux内核(基于6.x):解读Linux内存反向映射之匿名映射

文章目录 &#x1f4d1;前言一、匿名映射的mapping二、推荐阅读2.1 一图速览2.2 内容简介 &#x1f4d1;前言 内存映射中&#xff0c;我们经常讨论的是由虚拟内存定位物理内存&#xff08;也就是folio或者page&#xff09;&#xff0c;实际上在很多场景中&#xff08;比如内存回…

【C语言】C语言入门宝典:核心概念全解析

. C语言专栏 | C专栏 &#x1f449; 个人主页 &#x1f448; 前言 此篇文章我们主要是宏观的了解一下什么是C语言&#xff0c;C语言里面有那些知识点&#xff0c;所有的知识点我们此篇只是以入门为主&#xff0c;点到为止&#xff0c;简单易懂&#xff0c;后期的文章会一 一详…

【APP_PDD】数据采集案例拼多多APP_抓包分析_①

那远山呼唤我 曾千百次路过 半山腰摘几朵 便飘向歌颂者 那份简单 离开后 就再也没见过 单程票的火车 一路上哼着歌 &#x1f3b5; 王睿卓/Damn5z《重生之我在异乡为异客》 使用charles抓包 操作app后发现&#xff0c;刚打开app时可以抓到零散的数据包&am…

京东h5st4.73

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; lianxi a15018601872 …

Vue CLI,Vue Router,Vuex

前言 Vue CLI、Vue Router 和 Vuex 都是 Vue.js 生态系统中的重要组成部分&#xff0c;它们在构建 Vue 应用程序时扮演着关键角色。 Vue CLI Vue CLI 介绍 Vue CLI 是 Vue.js 的官方命令行工具&#xff0c;用于快速搭建 Vue.js 项目。它提供了一个图形界面&#xff08;通过…

C语言练习01-循环

一、打印五行五列的三角形 如下图&#xff1a; #include<stdio.h>int main() {for (int i 1;i < 5; i){for (int j i; j < 5; j){printf("*");}printf("\n");}return 0; }#include<stdio.h>int main() {for (int i 1;i < 5; i){f…

MATLAB直方图有关函数的关系

histogram Histogram plot画直方图 histcounts 直方图 bin 计数 histcounts是histogram的主要计算函数。 discretize 将数据划分为 bin 或类别 histogram2 画二元直方图 histcounts2 二元直方图 bin 计数 hist和histc过时了。替换不建议使用的 hist 和 histc 实例 hist → \r…

18个机器学习核心算法模型总结

最强总结&#xff01;18个机器学习核心算法模型&#xff01;&#xff01; 大家好~ 在学习机器学习之后&#xff0c;你认为最重要的算法模型有哪些&#xff1f; 今儿的内容涉及到~ 线性回归逻辑回归决策树支持向量机朴素贝叶斯K近邻算法聚类算法神经网络集成方法降维算法主成…

【因果推断python】44_评估因果模型2

目录 累积弹性曲线 累积增益曲线 考虑差异 关键思想 累积弹性曲线 再次考虑将价格转换为二元处理的说明性示例。我们会从我们离开的地方拿走它&#xff0c;所以我们有弹性处理带。我们接下来可以做的是根据乐队的敏感程度对乐队进行排序。也就是说&#xff0c;我们把最敏感…

day13 二叉树的遍历

一、二叉树的递归遍历 题目链接&#xff1a; 144.二叉树的前序遍历(opens new window)145.二叉树的后序遍历(opens new window)94.二叉树的中序遍历 文章讲解&#xff1a;https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%80%92%E5%BD%92%E9%81%8D%E5%8E…

苍穹外卖---编辑员工(P27-P29)

一、需求分析与设计 &#xff08;1&#xff09;产品原型 在员工管理列表页面点击 "编辑" 按钮&#xff0c;跳转到编辑页面&#xff0c;在编辑页面回显员工信息并进行修改&#xff0c;最后点击 "保存" 按钮完成编辑操作。 员工列表原型&#xff1a; 修改…

03 - matlab m_map地学绘图工具基础函数 - 设置坐标系(m_coord)

03 - matlab m_map地学绘图工具基础函数 - 设置坐标系&#xff08;m_coord&#xff09; 0. 引言1. m_proj使用方法2. 结语 0. 引言 上一篇介绍了m_proj函数用于初始化投影&#xff0c;本篇介绍的函数m_coord用于初始化地理坐标系或地磁坐标系&#xff0c;地理/地磁坐标系和投影…