Mybatis进阶(2)——为什么用mybatis? 多表查询解决 延迟加载 mybatis缓存 【未完待续】

news2024/10/5 14:21:55

目录

  • 引出
  • 一、为啥用mybatis?
  • 二、多表查询之一对多【待续】
    • 1.一对多的情况
    • 方案一:采用多表联查的方式
      • (1)resultMap
      • (2)查询的java接口和xml的SQL语句
      • (3)对应关系分析
      • (4)进阶版本,根据业主id查询房屋的sql不在当前的mapper中
    • 方案二:延迟加载 fetchType="lazy"
    • 方案三:业务拆解,查两次【建议】
      • (1)根据id查询业主
      • (2)根据业主id查询房子的list
      • (3)在service层【可变长度参数】
      • (4)在controller层调用service
  • 三、延迟加载
    • 为什么会有延迟加载
    • association例子
    • collection例子
  • 四、缓存【待续】
  • 总结

引出


1.mybatis可以实现SQL语句和Java代码的解耦;
2.多表查询,一对多情况的延迟加载 fetchType=“lazy”;
3.一对多的查询方式,建议查询两次,从业务和速度的角度;
4.延迟加载的association和 collection;
5.mybatis缓存,一级缓存,二级缓存;

一、为啥用mybatis?

mybatis 是一个优秀的基于 java 的持久层框架,主要应用于关系型数据库(sql),它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement ,封装数据等繁杂的过程。

在之前没有mybatis的时候,SQL语句和Java耦合

在这里插入图片描述

通过mybatis框架,就可以实现SQL和Java代码的解耦;
此外,在mybatis框架下,开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement ,封装数据等繁杂的过程。

在这里插入图片描述

二、多表查询之一对多【待续】

1.一对多的情况

一对多的表查询,比如想要查询一个人名下有多少套房子,也就是查询业主的时候,想要把业主名下的所有房子也查询出来

在这里插入图片描述

方案一:采用多表联查的方式

SELECT * FROM user_owner
LEFT JOIN c_owner_house ON c_owner_house.ownerId = user_owner.id
LEFT JOIN c_house ON c_owner_house.houseId = c_house.id

在这里插入图片描述

在mybatis里面,提供了多对一的查询方式

(1)resultMap

  • 用resultMap,建立业主实体类 和 数据库 表查询的 映射关系,property表示实体类的属性,column表示对应表的字段;
  • 查出来的list用collection定义关系,select 表示对应哪个mapper.xml中的哪条sql语句,column表示用上面查询出来的哪一个列名作为查询条件,property表示对应owner实体类的属性;
  • 其中,select 表示对应哪个mapper.xml中的哪条sql语句,在本案例中位于同一个mapper中;
<!--    建立业主实体类和 数据库 表查询的 映射关系 -->
    <resultMap id="ownerHouseList" type="com.tianju.entity.Owner">
<!--        业主实体类的字段映射,property实体类,column数据库表列名-->
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="realname" column="realname"></result>
        <result property="gender" column="gender"></result>
        <result property="password" column="password"></result>
        <result property="tel" column="tel"></result>
        <result property="identity" column="identity"></result>
        <result property="notes" column="notes"></result>
        <result property="createTime" column="create_time"></result>
        <result property="updateTime" column="update_time"></result>
        <result property="operator" column="operator"></result>
        <!--    查询一下业主拥有的房子,房子的list-->
<!--        select 对应哪个mapper 里面的 哪一条sql-->
<!--        column 用上面查询出来的哪一个列名 作为 查询条件-->
        <collection property="houseList" select="queryHouseByOwnerId" column="id"></collection>
    </resultMap>

上面的resultmap对应的实体类如下:

package com.tianju.entity;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

/**
 * 业主的实体类
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Owner implements Serializable { // 序列化
//public class Owner { // TODO:序列化,序列化是一级缓存和二级缓冲的事情
    private Integer id;
    private String username;
    private String realname; // 真实姓名
    private String gender;
    private String password;
    private String tel;
    private String identity;
    private String notes; // 备注信息
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date createTime;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date updateTime;
    private String operator;
    // 用户拥有的房间的list
    private List<House> houseList;
	// 拥有房子的数量
    private Integer houseNum;
}

House的实体类如下:

package com.tianju.entity;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

/**
 * 房屋的实体类,对应4表联查的实体类
 */
@Data
@NoArgsConstructor
@AllArgsConstructor

public class House {
    private Integer id; // 对应的是c_owner_house里面的id TODO:应该是房屋表的id
    private Integer buildingId; // 楼栋号
    private Integer floors; // 楼层总数
    private String num; // 楼栋,1栋,2栋...
    private String unit; // 单元,1单元,2单元...
    private Integer storey; // 楼层
    private String roomNum; // 房间号
    private Double area; // 房屋面积
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date intoDate; // 入住时间
    private Integer status;// 入住状态,0未入住,1入住
    private Integer ownerId; // 业主的id;
    private String ownerName; // 业主的真实姓名;
}

(2)查询的java接口和xml的SQL语句

    /**
     * TODO:延迟加载
     * 查询业主信息,同时获取业主名下所有的房屋信息
     * @param id
     * @return
     */
    Owner queryOwnerById(Integer id);

对应的xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tianju.dao.OwnerMapper">

<!--    TODO:延迟加载情况 ,查业主的时候,也要查出用户有的房子的list-->
<!--    建立业主实体类和 数据库 表查询的 映射关系 -->
    <resultMap id="ownerHouseList" type="com.tianju.entity.Owner">
<!--        业主实体类的字段映射,property实体类,column数据库表列名-->
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="realname" column="realname"></result>
        <result property="gender" column="gender"></result>
        <result property="password" column="password"></result>
        <result property="tel" column="tel"></result>
        <result property="identity" column="identity"></result>
        <result property="notes" column="notes"></result>
        <result property="createTime" column="create_time"></result>
        <result property="updateTime" column="update_time"></result>
        <result property="operator" column="operator"></result>
        <!--    查询一下业主拥有的房子,房子的list-->
<!--        select 对应哪个mapper 里面的 哪一条sql-->
<!--        column 用上面查询出来的哪一个列名 作为 查询条件-->
        <collection property="houseList" select="queryHouseByOwnerId" column="id"></collection>
    </resultMap>

<!--    查询出一个业主,TODO:注意这里是resultMap-->
    <select id="queryOwnerById" resultMap="ownerHouseList">
        SELECT * FROM user_owner WHERE id = #{id}
    </select>

    <!--    TODO:尝试用一下延迟加载,注意这里是resultType-->
    <select id="queryHouseByOwnerId" resultType="house">
        SELECT
        c_owner_house.*,
        c_building.num,c_building.floors,c_building.unit,
        c_house.storey,c_house.roomNum,c_house.area,c_house.into_date,c_house.status,c_house.building_id,
        user_owner.realname AS ownerName
        FROM c_house
        LEFT JOIN c_building ON c_building.id = c_house.building_id
        LEFT JOIN c_owner_house ON c_owner_house.houseId = c_house.id
        LEFT JOIN user_owner ON user_owner.id = c_owner_house.ownerId
        WHERE ownerId = #{ownerId}
    </select>

</mapper>

(3)对应关系分析

在这里插入图片描述

一个简化版本的例子,新闻和新闻的评论

在这里插入图片描述

(4)进阶版本,根据业主id查询房屋的sql不在当前的mapper中

则原来的collection改成:

<collection property="houseList" select="com.tianju.dao.HouseMapper.queryHouseByOwnerId" column="id"></collection>

在houseMapper.xml文件中

<!--    TODO:尝试用一下延迟加载-->
<!--    TODO:一个卡了一会儿的bug,这里要用resultType,而不是resultMap-->
    <select id="queryHouseByOwnerId" parameterType="integer" resultType="house">
        SELECT
        c_owner_house.*,
        c_building.num,c_building.floors,c_building.unit,
        c_house.storey,c_house.roomNum,c_house.area,c_house.into_date,c_house.status,c_house.building_id,
        user_owner.realname AS ownerName

        FROM c_house
        LEFT JOIN c_building ON c_building.id = c_house.building_id
        LEFT JOIN c_owner_house ON c_owner_house.houseId = c_house.id
        LEFT JOIN user_owner ON user_owner.id = c_owner_house.ownerId

        WHERE ownerId = #{ownerId}
    </select>

方案二:延迟加载 fetchType=“lazy”

在查看业主的基础信息时,其实并不需要知道业主名下的房屋信息,就比如看新闻的时候并不需要把评论也放出来,因此,可以采用需要的时候再查询房屋信息来实现一定程度的减少和数据库频繁交互;

延迟加载其实很简单,只需要加上在xml文件中的resultMap加上fetchType="lazy"即可

    <resultMap id="ownerHouseList" type="com.tianju.entity.Owner">
<!--        业主实体类的字段映射,property实体类,column数据库表列名-->
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="realname" column="realname"></result>
        <result property="gender" column="gender"></result>
        <result property="password" column="password"></result>
        <result property="tel" column="tel"></result>
        <result property="identity" column="identity"></result>
        <result property="notes" column="notes"></result>
        <result property="createTime" column="create_time"></result>
        <result property="updateTime" column="update_time"></result>
        <result property="operator" column="operator"></result>
        <!--    查询一下业主拥有的房子,房子的list-->
<!--        select 对应哪个mapper 里面的 哪一条sql-->
<!--        column 用上面查询出来的哪一个列名 作为 查询条件-->
<!--        fetchType lazy表示开启延迟加载 -->
        <collection property="houseList" select="com.tianju.dao.HouseMapper.queryHouseByOwnerId" column="id" fetchType="lazy"></collection>
    </resultMap>

对应的接口java

    /**
     * TODO:延迟加载
     * 查询业主信息,同时获取业主名下所有的房屋信息
     * @param id
     * @return
     */
    Owner queryLazyOwnerById(Integer id);

进行延迟加载的测试,只有用到houseList的时候,mybatis才会去查业主名下的房屋信息

(1)没有用到业主房屋的list

    @Test
    public void test(){
        // TODO:延迟加载的测试
        // 1.根据id查询业主,没有用到业主房屋的list,看执行了什么sql
        Owner ownerNoUseHouse = ownerMapper.queryLazyOwnerById(1);
        System.out.println(ownerNoUseHouse.getRealname());


        // 2.如果用到了业主房屋的list,看执行了什么sql
    }

在这里插入图片描述

(2)用到业主的房屋信息

    @Test
    public void lazy(){
        // TODO:延迟加载的测试
        // 1.根据id查询业主,没有用到业主房屋的list,看执行了什么sql
        Owner ownerNoUseHouse = ownerMapper.queryLazyOwnerById(1);
        // 2.如果用到了业主房屋的list,看执行了什么sql
        System.out.println("####################");
        System.out.println(ownerNoUseHouse);
    }

在这里插入图片描述

完整的SpringBootTest代码

package com.tianju;

import com.tianju.dao.HouseMapper;
import com.tianju.dao.OwnerMapper;
import com.tianju.entity.House;
import com.tianju.entity.Owner;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * spring的测试类 @SpringBootTest
 */
@SpringBootTest
public class SpringTest {
    @Autowired
    private OwnerMapper ownerMapper;

    @Autowired
    private HouseMapper houseMapper;

    @Test
    public void test(){
        // TODO:延迟加载的测试
        // 1.根据id查询业主,没有用到业主房屋的list,看执行了什么sql
        Owner ownerNoUseHouse = ownerMapper.queryLazyOwnerById(1);
        System.out.println(ownerNoUseHouse.getRealname());


        // 2.如果用到了业主房屋的list,看执行了什么sql
    }

    @Test
    public void lazy(){
        // TODO:延迟加载的测试
        // 1.根据id查询业主,没有用到业主房屋的list,看执行了什么sql
        Owner ownerNoUseHouse = ownerMapper.queryLazyOwnerById(1);
        // 2.如果用到了业主房屋的list,看执行了什么sql
        System.out.println("####################");
        System.out.println(ownerNoUseHouse);
    }

}

方案三:业务拆解,查两次【建议】

从业务的角度,以及速度的角度,应该如下操作:

  • 1.一般情况下,只需要根据id查询出业主的基础信息,此时只执行一条SQL语句;
  • 2.如果需要用到业主名下的房屋信息,就再执行一条SQL,根据id查询业主名下的房屋数据;

在这里插入图片描述

第一种情况:只需要业主的基础信息,此时不需要查询房屋信息

在这里插入图片描述

第二种情况,如果点击查看详情,此时既要业主的基础信息,也要查询房屋信息,就执行两条SQL

在这里插入图片描述

(1)根据id查询业主

    /**
     * 上面这种延迟加载的方式不建议,应该这样做
     * TODO:从业务角度,和速度角度
     * 1.一般情况下,只需要根据id查询出业主;
     * 2.如果需要用到业主名下的房屋,再根据业主id查方法
     */
    Owner queryById(Integer id);
    <select id="queryById" resultType="owner">
        SELECT * FROM user_owner WHERE id = #{id}
    </select>

(2)根据业主id查询房子的list

    /**
     * 根据业主的id,查询该业主名下有哪些房子
     * @param ownerId 业主的id
     * @return 名下房子的list
     */
    List<House> queryHouseByOwnerId(Integer ownerId);
    <select id="queryHouseByOwnerId" parameterType="integer" resultType="house">
        SELECT
        c_owner_house.*,
        c_building.num,c_building.floors,c_building.unit,
        c_house.storey,c_house.roomNum,c_house.area,c_house.into_date,c_house.status,c_house.building_id,
        user_owner.realname AS ownerName

        FROM c_house
        LEFT JOIN c_building ON c_building.id = c_house.building_id
        LEFT JOIN c_owner_house ON c_owner_house.houseId = c_house.id
        LEFT JOIN user_owner ON user_owner.id = c_owner_house.ownerId

        WHERE ownerId = #{ownerId}
    </select>

(3)在service层【可变长度参数】

package com.tianju.service;

import com.tianju.entity.Owner;

public interface IOwnerService {
    /**
     * 默认情况下只查询这个用户的基础信息,
     * 如果需要房屋信息,就再查一下房屋信息
     * @param id 查询的业主的id
     * @param isGetHouse 是否获取房屋信息,默认不获取,true表示获取
     * @return
     */
    Owner queryById(Integer id,Boolean... isGetHouse);

    /**
     * 新增一条用户信息
     */
    Integer add(Owner owner);
}

package com.tianju.service.impl;

import com.tianju.dao.HouseMapper;
import com.tianju.dao.OwnerMapper;
import com.tianju.entity.House;
import com.tianju.entity.Owner;
import com.tianju.service.IOwnerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Transactional
public class OwnerServiceImpl implements IOwnerService {
    @Autowired
    private OwnerMapper ownerMapper;

    @Autowired
    private HouseMapper houseMapper;

    @Override
    public Owner queryById(Integer id,Boolean... isGetHouse) {
        // TODO:尽量减少和数据库的交互
        Owner owner = ownerMapper.queryById(id);
        if (isGetHouse!=null && isGetHouse[0]){
            // 表示既要业主的信息,也要业主名下的房屋的信息
            List<House> houseList = houseMapper.queryHouseByOwnerId(id);
            owner.setHouseList(houseList);
            // 既然查询了一下该业主的房屋数量,那就更新一下拥有房间数量
            ownerMapper.updateOwnerHouseNum(id, houseList.size());
            return owner;
        }
        return owner;
    }

    @Override
    public Integer add(Owner owner) {
        // 如果新用户只是意向客户
        if (owner.getHouseList().size()<1){
            owner.setHouseNum(0);
            return ownerMapper.add(owner);
        }
        // 买房的客户变成了业主
        Integer num = 0; //影响数据库的数据的行数
        ownerMapper.add(owner);
        for (House house:owner.getHouseList()){
            // 房间状态改为入住的状态
            houseMapper.intoHouse(house.getId());
            // 房屋-业主对应表新增一条数据
            houseMapper.addOwnerHouse(owner.getId(), house.getId());
            num +=2;
        }
        return num;
    }
}

(4)在controller层调用service

    // 查询出用户的详细信息,需要查用户名下房子的信息
    @RequestMapping("/detail")
    @ResponseBody
    public ResData detail(Integer id){
        if (StringUtils.isBlank(id)){
            return new ResData(1001, "id为空", null);
        }
        Owner owner = ownerService.queryById(id, true);
        if (owner==null){
            return new ResData(1002,"未找到",null);
        }
        return new ResData(200, "ok", owner);
    }

三、延迟加载

实际开发经验中,很多时候可能只是需要用户信息,然后通过用户去查询角色时,也就是说,加载用户信息时不一定要同时加载角色信息。此时就是延迟加载。

为什么会有延迟加载

select * from account where id=1  //先查询出这个账户信息,包含uid
select * from user where uid=1     //再查询用户信息

延迟加载: 延迟加载也叫懒加载,是针对级联使用的,懒加载的目的是减少内存的浪费和减轻系统负担。

好处:
先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

坏处:
因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,其实是二次连接查询,所以速度反而下降,让数据库的压力显得不平滑。

需求:

查询账户(Account)信息并且关联查询用户(User)信息。如果先查询账户(Account)信息即可满足要求,当我们需要查询用户(User)信息时再去查询用户(User)信息。把对用户(User)信息的按需去查询就是延迟加载。

我们使用多对多的关系,主要是通过 association、collection 实现映射。而association、collection 具备延迟加载功能。

如果某个collection不想用懒加载,可以使用 fetchType=“eager”,默认是fetchType=“lazy”,高版本有修改,fetchType需要自己添加

association例子

association用于一对一、多对一场景使用

    <resultMap id="accountMap2" type="account">
        <id column="id" property="id"/>
        <result column="uid" property="uid"/>
        <result column="money" property="money"/>

        <association property="user" javaType="user"
        		select="com.tianju.mapper.UserMapper.findById" column="uid">
        </association>
    </resultMap>
    
    <select id="findAll2" resultMap="accountMap2">
        select * from account
    </select>
    @Test
    public void findAll2(){
        List<Account> all2 = accountMapper.findAll2();
        //User user = all2.get(0).getUser();
    }

collection例子

   <resultMap id="userMap2" type="user">
        <id column="id" property="id"></id>
        <result column="username" property="username"/>
        <result column="address" property="address"/>
        <result column="sex" property="sex"/>
        <result column="birthday" property="birthday"/>

       <collection property="accounts" ofType="account" fetchType="lazy"
        select="com.woniu.mapper.AccountMapper.findByUid" column="id">
        </collection>
    </resultMap>

    <select id="findAll2" resultMap="userMap2">
        select * from user;
    </select>

collection:是用于建立一对多中集合属性的对应关系

ofType : 用于指定集合元素的数据类型

select : 是用于指定查询账户的唯一标识(账户的 mapper 全限定类名加上方法名称)

column :是用于指定使用哪个字段的值作为条件查询

四、缓存【待续】

缓存是什么?在mybatis中,缓存就是,第一次查询数据库以后,把结果存起来,如果下一次查询参数没改变,并且对应要查询的表也没有改变,就可以直接从存的地方来拿,这就是缓存技术。

mybatis的缓存分为一级缓存,和二级缓存。

其中一级缓存是系统自带的缓存,只要sqlsession没有变化,他就一直存在

二级缓存是在namespace阶段,也就是每一个mapper.xml中,需要开启才能使用。我们先讲一级缓存

缓存失效的情况:

sqlsession关闭,一级缓存失效

两次查询中间,数据库表有变动,缓存失效


总结

1.mybatis可以实现SQL语句和Java代码的解耦;
2.多表查询,一对多情况的延迟加载 fetchType=“lazy”;
3.一对多的查询方式,建议查询两次,从业务和速度的角度;
4.延迟加载的association和 collection;
5.mybatis缓存,一级缓存,二级缓存;

在这里插入图片描述

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

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

相关文章

使用docker搭建minio分布式对象存储系统

使用docker搭建minio分布式对象存储系统 这里我简单的和大家介绍一下什么是minio &#xff1f; 附上Minio官网链接&#xff1a;https://minio.org.cn/ MinIO是一种开源的对象存储服务器&#xff0c;通过使用标准的HTTP/REST API来访问和管理数据。它采用分布式架构&#xff0c…

【SAP UI5 控件学习】DAY02 Input组PartII

1. CheckBox控件 1.1 最普通的CheckBox <CheckBox text"Option a" selected"true" />如果需要设置选中状态&#xff0c;需要设置selected属性为true 1.2 部分选中CheckBox <CheckBox text"Option partially selected" selected"t…

【ElasticSearch】DSL查询语法

文章目录 1、DSL查询分类2、DSL基本语法3、全文检索查询4、精确查询5、地理查询6、复合查询--相关性打分算法7、复合查询之Function Score Query8、复合查询之BooleanQuery 1、DSL查询分类 Elasticsearch提供了基于JSON的DSL&#xff08;Domain Specific Language&#xff09;…

【ARM Coresight 系列文章 2 - ARM Coresight 介绍】

文章目录 1.1 ARM Coresight 介绍1.1.1 ARM Coresight 发展历史 1.2 ARM Coresight 框架介绍1.1.1 Trace 通路1.1.3 Debug 通路1.1.4 Trigger 通路 1.1 ARM Coresight 介绍 ARM Coresight是ARM公司提供的一种调试和跟踪技术&#xff0c;用于ARM处理器的调试和性能分析。它通过…

Java中规模软件开发实训——简单的文本编辑器(代码注释详解)

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;html css js&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;在现代社会中…

k8s如何伸缩应用程序和执行滚动更新

一、伸缩应用程序 我们创建了一个 Deployment (opens new window)&#xff0c;然后通过 服务 (opens new window)提供访问 Pod 的方式。我们发布的 Deployment 只创建了一个 Pod 来运行我们的应用程序。当流量增加时&#xff0c;我们需要对应用程序进行伸缩操作以满足系统性能…

第五章:L2JMobius学习 – 快速部署L2JMobius汉化版

L2JMobius是一套开源的 LineageII 的服务器端代码&#xff0c;使用Java语言编写。在前面的章节中&#xff0c;我们安装了mariadb10数据库以及jdk17运行环境&#xff0c;这两个是必须的。紧接着&#xff0c;我们又安装了eclipse开发工具&#xff0c;然后创建了“L2J_Mobius”Jav…

按键输入实验(stm32)

目录 按键的相关代码key.ckey.h LED的相关代码BEEP的相关代码beep.cbeep.h main.c代码的相关说明相关硬件说明实验结果 说明&#xff1a;以下内容参考正点原子资料 按键的相关代码 key.c void KEY_Init(void) //IO初始化 { GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2Peri…

ModaHub魔搭社区:可视化的AI原生云向量数据库 Milvus 2.2.9 :JSON、PartitionKey、Dynamic Schema

目录 新特性 功能增强 其他优化 问题修复 亮点颇多、精彩程度堪比大版本的 Milvus 2.2.9 来啦&#xff01; 随着 LLM 的持续火爆&#xff0c;众多应用开发者将目光投向了向量数据库领域&#xff0c;而作为开源向量数据库的领先者&#xff0c;Milvus 也充分吸收了大量来自社…

ROS:话题名称设置

目录 一、 前言二、rosrun设置话题重映射三、launch文件设置话题重映射四、编码设置话题名称4.1C4.1.1全局名称4.1.2相对名称4.1.3私有名称 4.2Python 实现4.2.1全局名称4.2.2相对名称4.2.3私有名称 一、 前言 在ROS中节点名称可能出现重名的情况&#xff0c;同理话题名称也可…

[攻防世界] [RE] [APK] app2

解题思路 导入jadx查看manifest.xml 查看主函数并未发现有价值的东西&#xff0c;于是查看manifest.xml中主函数下一个<activity> 截取FileDataActivity代码 package com.tencent.testvuln;import android.os.Bundle; import android.widget.TextView; import com.tence…

2022年真题 - 15 - 磁盘管理(vdo磁盘)

磁盘管理 - vdo磁盘 题目配置验证配置题目 StorageSrv - 磁盘管理 在 storagesrv 上新加一块 10G 磁盘;创建 vdo 磁盘,并开启 vdo 磁盘的重删和压缩;名字为 vdodisk,大小为150G,文件系统为 ext4;并设置开机自动挂载。挂载到 /vdodata。配置 新加一块 10G 磁盘; 安装…

驱动 作业 day4

编写LED灯的驱动&#xff0c;创建三个设备文件&#xff0c;每个设备文件和一个LED灯绑定&#xff0c;当操作这个设备文件时只能控制设备文件对应的这盏灯。 此时没有安装led2 和led3的驱动所以会打开设备文件失败 装完以后就可以正常控制了 以下是设备现象 head.h ubuntuu…

docker 的整体架构及各模块组件 《深入docker底层原理》

1.Docker 整体架构 Docker 是一个 C/S 模式的架构&#xff0c;后端是一个松耦合架构&#xff0c;模块各司其职。 1、用户是使用 Docker Client 与 Docker Daemon 建立通信&#xff0c;并发送请求给后者。 2、Docker Daemon 作为 Docker 架构中的主体部分&#xff0c;首先提供…

Windows如何设置自动关闭未响应的程序?Windows设置自动关闭未响应的程序方法,带图详解

Windows系统程序经常出现程序未响应现象&#xff0c;如何通过注册表使其自动关闭呢 1、首先快捷键winR唤出【运行】 输入regedit 2、确定后就打开了注册表编辑器&#xff0c;定位到【HKEY_CURREnT_UsER\Control panel\desktop】项下 3、在右侧找【AutoEndTasks】数值数据&#…

yolo.h5文件问题的解决 - 吴恩达深度学习:目标检测之YOLO算法

1.下载下载yad2k: git clone https://github.com/allanzelener/yad2k.git 这里面顺便有yad2k.py文件 2.下载yolov2.cfg https://github.com/pjreddie/darknet/tree/master/cfg 3.下载yolov2.weights http://pjreddie.com/media/files/yolo.weights 需要这三个文件 自己去githup…

易模为真人3D手办制作带来了创新

3d打印技术是一项近年来迅速发展的先进制造技术&#xff0c;逐渐在各个领域展现出无限的潜力。其中&#xff0c;3d打印真人手办成为了一个备受关注的领域。在市面上&#xff0c;我们常常可以看到一些热门动漫角色或明星的真人3d手办&#xff0c;逼真的细节和完美的再现度让人们…

iOS上架报错:无法添加以供审核

无法提交以供审核 要开始审核流程 必须提供以下项目 您必须为要添加的 app 提供版权信息。 您在提交 app 审核时遇到的问题是因为需要提供版权信息&#xff0c;而您的 app 缺少相关的版权信息。以下是解决此问题的步骤&#xff1a; 确认您是否拥有 app 的版权&#xff1a;在提…

mac苹果电脑,怎么把mkv转换mp4格式

mac苹果电脑&#xff0c;怎么把mkv转换mp4格式&#xff1f;如果你是一名mac苹果电脑的用户&#xff0c;在电脑上下载到mkv格式的视频后会发现它使用起来非常的麻烦&#xff0c;甚至不能直接打开播放。mkv其实也是一种时间比较久远的视频文件格式&#xff0c;但是不知道是什么原…

eNSP-OSPF组播拓展

OSPF组播拓展 文章目录 OSPF组播拓展一、拓扑结构二、基础配置三、测试验证 启动 OSPF 协议后 &#xff0c; OSPF 将向本地所有运行 OSPF 协议的接口以组播224.0.0.5的形式发送hello报 文 &#xff1b; hello 报文中将携带本地 RID 值 &#xff0c; 以及本地已知的邻居的RID值&…