MyBatisPlus——入门到进阶

✅作者简介:大家好,我是 Meteors., 向往着更加简洁高效的代码写法与编程方式,持续分享Java技术内容。
🍎个人主页:Meteors.的博客
💞当前专栏:知识分享、知识备份
✨特色专栏: 知识分享
🥭本文内容:MyBatisPlus——入门到进阶
📚 ** ps **  : 阅读文章如果有问题或者疑惑,欢迎在评论区提问或指出。


目录

01. 入门

1. 添加依赖

2. Mapper继承BaseMapper接口

02. 常见注解

1. 说明

 2. 例子

03. 常见配置

03. 常见配置

04. 核心功能-条件构造器

1. 说明

2. 例子

05. 核心功能-自定义SQL

1. 说明

2. 步骤

a. 基于Wrapper构建where条件

b. 在mapper方法中用Param注解声明wrapper变量名称,必须是ew

c.定义SQL,并使用Wrapper条件

06. 核心功能-Service接口

1. 说明

2. 步骤

a. Service层继承IService接口

b. Service实现类继承(Impl)继承ServiceImpl

c. 调用方法(以save为例,更多例子点击这里)

3. 补充

07. 扩展功能-代码生成 

方式一:使用代码生成器代码进行生成

方式二:使用MybatisX进行代码生成(这个会少一个controller)

方式三:使用应用商店的MybatisPlus插件进行代码生成

08. 扩展功能-静态工具

1.说明

2. 例子

09. 扩展功能-逻辑删除

1. 说明

2. 例子

3. 补充(引用自黑马视频)

10.  扩展功能-枚举处理器

1. 说明

2. 例子

11. 扩展功能-JSON处理器

1. 说明

2. 例子

 12. 插件功能-分页插件

1. 说明

2. 例子


01. 入门

1. 添加依赖

<!--        <dependency>-->
<!--            <groupId>org.mybatis.spring.boot</groupId>-->
<!--            <artifactId>mybatis-spring-boot-starter</artifactId>-->
<!--            <version>2.3.1</version>-->
<!--        </dependency>-->
        <!--    MyBatisPlus依赖    -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.6</version>
        </dependency>

2. Mapper继承BaseMapper接口

// 类似于
public interface UserMapper extend BaeMapper<User>{


}

02. 常见注解

1. 说明

mp通过扫描实体类,并基于反射获取实体类信息作为数据库表信息,比较常用的注解如下:

  • @TableName:指定表名
  • @TableId:用来指定表中的主键字段信息
    • idType枚举说明:
      • ATUO:数据库自增
      • INPUT:通过set方法自行输入
      • ASSUGN_ID:分配ID(接口IdentifierGenerator的方法nextId来生成id,默认实现类为DefaultIdentifierGenerator雪花算法)
  • @TableField:用来指定表中的普通字段信息
    • 使用场景:
      • 成员变量名宇数据库字段名不一致
      • 成员变量名以is开头,且是布尔值
      • 成员变量名宇数据库关键字冲突
      • 成员变量不是数据库字段

 2. 例子

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.time.LocalDateTime;

@Data
@TableName("tb_user")
public class User {

    /**
     * 用户id
     */
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 用户名
     */
    @TableField("`username`")
    private String username;

    /**
     * 密码
     */
    @TableField(exist = false)
    private String password;

    /**
     * 注册手机号
     */
    private String phone;

    /**
     * 详细信息
     */
    private String info;

    /**
     * 使用状态(1正常 2冻结)
     */
    private Integer status;

    /**
     * 账户余额
     */
    private Integer balance;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;
}

03. 常见配置

03. 常见配置

mybatis-plus:
  configuration:
    # MyBatis 配置
    map-underscore-to-camel-case: true
    # 扫描包
  global-config:
    # 全局配置
    db-config:
      # 数据库配置
      id-type: auto
  # 包的位置
  type-aliases-package: com.itmeteors.mp.domain.po

04. 核心功能-条件构造器

1. 说明

mp为我们提供了的条件构造器方法,以便与我们进行查询操作:

2. 例子

    // 01. 查询出名字中带o的,存款大于1000元人的id、userName、info、balance
    @Test
    void testQueryWrapper(){
    //    1. 构建查询条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .select("id", "username", "info", "balance")
                .like("username", "o")
                .ge("balance", 1000);
        //    2. 查询
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }
    // 02. 更新用户名为jack的用户的余额为2000
    @Test
    void testUpdateByQueryWrapper(){
    //    1. 要更新的数据
        User user = new User;
        user.setBalance(2000);
    //    2. 更新要的条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username", "jack");
    //    3. 执行更新
        userMapper.update(user,wrapper);
    }
    // 03. 更新id为1,2,4的用户的余额,扣200
    @Test
    void testUpdateWrapper(){
        List<Long> ids = List.of(1L,2L,4L);
        UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
                .setSql("balance = balance - 200")
                .in("id",ids);
        userMapper.update(null,wrapper);
    }
    // 04. 使用lambada方式更新id为1,2,4的用户的余额,扣200
    @Test
    void testLambadaUpdateWrapper(){
        List<Long> ids = List.of(1L,2L,4L);
        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<User>()
                .setSql("balance = balance - 200")
                .in(User::getId,ids);
        userMapper.update(null,wrapper);
    }

05. 核心功能-自定义SQL

1. 说明

利用mp来构建复杂的Where条件,然后自己定义SQL语句中剩下的部分。

2. 步骤

a. 基于Wrapper构建where条件

    @Test
    void testUpdateWrapper2(){
    //    1. 更新条件
        List<Long> ids = List.of(1L, 2L, 4L);
        int amount = 200;
    //    2. 定义条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>().in("id", ids);
    //    3. 调用自定义SQL方法
        userMapper.updateBalanceByIds(wrapper,amount);
    }

b. 在mapper方法中用Param注解声明wrapper变量名称,必须是ew

    void updateBalanceByIds(@Param(Constants.WRAPPER) QueryWrapper<User> wrapper,@Param("amount") int amount);

c.定义SQL,并使用Wrapper条件

    <update id="updateBalanceByIds">
        UPDATE tb_user SET balance = balance - #{amount} ${ew.customSqlSegment}
    </update>

06. 核心功能-Service接口

1. 说明

mp的service接口为我们定义了很多增删改查的方法,减少了在service层的代码书写量

2. 步骤

a. Service层继承IService接口

public interface IUserService extends IService<User> {

}

b. Service实现类继承(Impl)继承ServiceImpl

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

}

c. 调用方法(以save为例,更多例子点击这里)

@SpringBootTest
class IUserServiceTest {
    @Autowired
    private IUserService userService;

    @Test
    void testSaveUser(){
        User user = new User();
        user.setUsername("tesst");
        user.setPassword("123");
        user.setPhone("15966666666");
        user.setBalance(200);
        user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        userService.save(user);
    }
}

3. 补充

使用 saveBatch()方法 默认不生效:

原因:虽然执行了批量插入方法,但是语句未被合并并优化,然后还是多个请求单独发送给MySQL服务器,网络往返次数和服务器解析SQL语句的开销未减少

解决方法:在yml的数据库连接url最后加上: rewriteBatchedStatements=true,允许驱动程序重写批处理语句为单个字符串,并发送给服务器,从而提高插入、更新和删除操作的速度。

当然,这样可能也会有缺点:

  1. SQL注入风险:因为语句被重写,所以可能会增加SQL注入的风险。务必确保你使用的SQL语句是安全的,避免直接拼接用户输入。
  2. 不支持所有SQL语法:某些复杂的SQL语法可能不支持重写。
  3. 调试困难:由于语句被重写,所以在调试时可能更难以确定问题所在。

07. 扩展功能-代码生成 

方式一:使用代码生成器代码进行生成

步骤:

  1. 导入依赖
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-generator</artifactId>
        <version>3.5.6</version>
    </dependency>
  2. 配置生成器类
    public class CodeGenerator {
        public static void main(String[] args) {
            FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true"
                            , "root"
                            , "****")
                    .globalConfig(builder -> {
                        builder.author("Meteors") // 设置作者
                                .enableSwagger() // 开启 swagger 模式
                                .outputDir("C:\\Users\\Meteors\\Desktop\\SpringCloud微服务—资料\\day01-MybatisPlus\\资料\\mp-demo\\src\\main\\java"); // 指定输出目录
                    })
                    .dataSourceConfig(builder ->
                            builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
                                int typeCode = metaInfo.getJdbcType().TYPE_CODE;
                                if (typeCode == Types.SMALLINT) {
                                    // 自定义类型转换
                                    return DbColumnType.INTEGER;
                                }
                                return typeRegistry.getColumnType(metaInfo);
                            })
                    )
                    .packageConfig(builder ->
                            builder.parent("com.itheima.mp") // 设置父包名
                                    .entity("domain.po") // 设置实体类包名
                                    .pathInfo(Collections.singletonMap(OutputFile.xml
                                            , "C:\\Users\\Meteors\\Desktop\\SpringCloud微服务—资料\\day01-MybatisPlus\\资料\\mp-demo\\src\\main\\resources\\mapper")) // 设置mapperXml生成路径
                    )
                    .strategyConfig(builder ->
                            builder.addInclude("address") // 设置需要生成的表名
                                    .addTablePrefix("t_", "c_") // 设置过滤表前缀
                                    .entityBuilder()
                                    .enableLombok() // 启用 Lombok
                                    .enableTableFieldAnnotation() // 启用字段注解
                                    .controllerBuilder()
                                    .enableRestStyle() // 启用 REST 风格
                    )
                    .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                    .execute();
        }
    }
    

  3. 运行代码

方式二:使用MybatisX进行代码生成(这个会少一个controller)

步骤:

  1. 选择MybatisX:
  2. 选择

方式三:使用应用商店的MybatisPlus插件进行代码生成

步骤:

  1. 下载插件
  2. 重启idea,并配置数据库
  3. 进行代码生成

08. 扩展功能-静态工具

1.说明

使用静态工具可以避免循环依赖问题。

2. 例子

需求(如果普通方式进行实现,下面两个需求可能会造成循环依赖)

  • 改造更具id查询用户的接口,查询用户的同时,查询出用户对应的所有地址
    //Controller
        @ApiOperation("根据id查询用户接口")
        @GetMapping("{id}")
        public UserVO queryUserById(@ApiParam("用户id") @PathVariable("id") Long id) {
            return userService.queryUserAndAddressById(id);
        }
    //Service
        UserVO queryUserAndAddressById(Long id);
    //Impl
        @Override
        public UserVO queryUserAndAddressById(Long id) {
            //    1. 查询用户
            User user = getById(id);
            if (user == null || user.getStatus() == 2) {
                throw new RuntimeException("用户状态异常!");
            }
            //    2. 查询地址
            List<Address> addressList = Db.lambdaQuery(Address.class).eq(Address::getUserId, id).list();
            //  3. 封装VO
            UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
            if (CollUtil.isNotEmpty(addressList)){
                userVO.setAddresses(BeanUtil.copyToList(addressList, AddressVO.class));
            }
            return userVO;
        }
  • 改造根据id批量查询用户的接口,查询用户的同时,查询出用户对应的所有地址
    // Controller
        @ApiOperation("根据id批量查询用户接口")
        @GetMapping
        public List<UserVO> queryUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids) {
            return userService.queryUserAndAddressByIds(ids);
        }
    // Service
        List<UserVO> queryUserAndAddressByIds(List<Long> ids);
    // Impl
        @Override
        public List<UserVO> queryUserAndAddressByIds(List<Long> ids) {
            // 1. 查询用户
            List<User> users = listByIds(ids);
            if (CollUtil.isEmpty(users)) {
                return Collections.emptyList();
            }
            // 2. 查询地址
            // 2.1 获取用户id集合
            List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());
            // 2.2 根据用户id查询地址
            List<Address> addresses = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list();
            // 2.3 转换地址VO
            List<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class);
            // 2.4 用户地址集合分组处理,相同用户的放入一个集合(组)中
            Map<Long, List<AddressVO>> addressMap = new HashMap<>(0);
            if (CollUtil.isNotEmpty(addressVOList)) {
                addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));
            }
            // 3. 转换VO返回
            List<UserVO> list = new ArrayList<>(users.size());
            for (User user : users) {
            //    3.1 转换User的PO为VO
                UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
            //    3.2 转换地址VO
                vo.setAddresses(addressMap.get(user.getId()));
            //    3.3 添加到集合
                list.add(vo);
            }
            return list;
        }

09. 扩展功能-逻辑删除

1. 说明

逻辑删除解释基于代码逻辑模拟删除效果,但并不会真正删除数据。思路:

  • 在表中添加一个字段标记数据是否被删除
  • 当删除数据时把标记置为1
  • 查询时值查询标记为0的数据

例如逻辑删除字段为deleted:

  • 删除操作:UPDATE user SET deleted = 1 WHERE id = 1 AND deleted = 0;
  • 查询操作:SELECT * FROM  user WHERE deleted = 0; 

mp提供了逻辑删除功能,无需改变方法调用的方式,而是在底层帮我们自动修改CRUD的语句。我们要做的就是在application.yaml文件中配置逻辑删除的字段名称和值即可:

2. 例子

在使用mp的逻辑删除功能之后,原有的查询功能会默认在末尾添加查询条件,删除功能会自动变更为UPDATE,下面是具体的例子:

  • 代码
@SpringBootTest
class IAddressServiceTest {
    @Autowired
    private IAddressService addressService;
    @Test
    void testLogicDelete(){
    //    1. 删除
        addressService.removeById(59L);
    //  2. 查询
        Address address = addressService.getById(59L);
        System.out.println("address = " + address);
    }
}
  • 结果

3. 补充(引用自黑马视频)

逻辑删除本身也有自己的问题,比如:

  • 会导致数据库表垃圾数据越来越多,影响查询效率
  • SQL中全部需要对逻辑删除字段做判断,影响查询效率

因此,需要进行逻辑删除时,可以考虑把数据迁移到其它表的方法进行替代

10.  扩展功能-枚举处理器

1. 说明

用户状态字段如果用例如private Integer status的方式进行表示,用这种类型表示不直观且代码且属于硬编码,可维护性差、灵活性低、可扩展性差、可读性差、重用性受限、错误分险增加,而使用mp枚举处理器,可以避免这些缺点。

2. 例子

将原有的状态字段改为枚举类型:

  1. 步骤1:在yaml文件中设置枚举处理器
  2. 步骤2:新建枚举类
    @Getter
    public enum UserStatus {
        NORMAL(1,"正常"),
        FROZEN(2,"冻结"),
        ;
        @EnumValue
        private final int value;
        @JsonValue
        private final  String desc;
    
        UserStatus(int value, String desc) {
            this.value = value;
            this.desc = desc;
        }
    }
  3. 步骤3:将字段类型替换为枚举类型
        /**
         * 使用状态(1正常 2冻结)
         */
        private UserStatus status;
  4. 结果:

11. 扩展功能-JSON处理器

1. 说明

当数据中的表中含有json类型的字段时,如果自己实现Java代码实体类与之对应,比较麻烦,此时可以使用mp的json处理器进行实现,提高开发效率。

2. 例子

将一个数据库中使用json类型的info属性,使用 json处理让Java实体类与之对应,步骤:

  1. 新建那个属性的实体类
    @Data
    @NoArgsConstructor
    @AllArgsConstructor(staticName = "of")
    public class UserInfo {
        private Integer age;
        private String intro;
        private String gender;
    }
  2. 字段上定义处理器并在实体类上开启autoResultMap

ps:

  • 赋值方式
//user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");
user.setInfo(UserInfo.of(24,"英语老师","female"));
  • 结果

 12. 插件功能-分页插件

1. 说明

在mp3.4版本之后,mp已经默认集成了mp插件,但如果需要对分页的功能(例如溢出总页数后是否进行处理、单页条数限制、数据库类型设置、方言实现设置)等,仍需要新建分页插件进行实现。

2. 例子

以新建一个的分页插件和通过分页实体实现分页功能为例,步骤如下:

  1. 添加分页插件
    package com.itheima.mp.config;
    
    import com.baomidou.mybatisplus.annotation.DbType;
    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class MyBatisConfig {
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            //  1. 创建分页插件
            PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
            paginationInnerInterceptor.setMaxLimit(1000L);
            //  2. 添加分页插件
            interceptor.addInnerInterceptor(paginationInnerInterceptor);
            return interceptor;
        }
    }
    
  2. 新建分页实体
    @Data
    public class PageQuery {
        private Integer pageNo;
        private Integer pageSize;
        private String sortBy;
        private Boolean isAsc;
    
        public <T>  Page<T> toMpPage(OrderItem ... orders){
            // 1.分页条件
            Page<T> p = Page.of(pageNo, pageSize);
            // 2.排序条件
            // 2.1.先看前端有没有传排序字段
            if (sortBy != null) {
                p.addOrder(new OrderItem(sortBy, isAsc));
                return p;
            }
            // 2.2.再看有没有手动指定排序字段
            if(orders != null){
                p.addOrder(orders);
            }
            return p;
        }
    
        public <T> Page<T> toMpPage(String defaultSortBy, boolean isAsc){
            return this.toMpPage(new OrderItem(defaultSortBy, isAsc));
        }
    
        public <T> Page<T> toMpPageDefaultSortByCreateTimeDesc() {
            return toMpPage("create_time", false);
        }
    
        public <T> Page<T> toMpPageDefaultSortByUpdateTimeDesc() {
            return toMpPage("update_time", false);
        }
    }
    
  3. 新建分页返回实体
    
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class PageDTO<V> {
        private Long total;
        private Long pages;
        private List<V> list;
    
        /**
         * 返回空分页结果
         * @param p MybatisPlus的分页结果
         * @param <V> 目标VO类型
         * @param <P> 原始PO类型
         * @return VO的分页对象
         */
        public static <V, P> PageDTO<V> empty(Page<P> p){
            return new PageDTO<>(p.getTotal(), p.getPages(), Collections.emptyList());
        }
    
        /**
         * 将MybatisPlus分页结果转为 VO分页结果
         * @param p MybatisPlus的分页结果
         * @param voClass 目标VO类型的字节码
         * @param <V> 目标VO类型
         * @param <P> 原始PO类型
         * @return VO的分页对象
         */
        public static <V, P> PageDTO<V> of(Page<P> p, Class<V> voClass) {
            // 1.非空校验
            List<P> records = p.getRecords();
            if (records == null || records.size() <= 0) {
                // 无数据,返回空结果
                return empty(p);
            }
            // 2.数据转换
            List<V> vos = BeanUtil.copyToList(records, voClass);
            // 3.封装返回
            return new PageDTO<>(p.getTotal(), p.getPages(), vos);
        }
    
        /**
         * 将MybatisPlus分页结果转为 VO分页结果,允许用户自定义PO到VO的转换方式
         * @param p MybatisPlus的分页结果
         * @param convertor PO到VO的转换函数
         * @param <V> 目标VO类型
         * @param <P> 原始PO类型
         * @return VO的分页对象
         */
        public static <V, P> PageDTO<V> of(Page<P> p, Function<P, V> convertor) {
            // 1.非空校验
            List<P> records = p.getRecords();
            if (records == null || records.size() <= 0) {
                // 无数据,返回空结果
                return empty(p);
            }
            // 2.数据转换
            List<V> vos = records.stream().map(convertor).collect(Collectors.toList());
            // 3.封装返回
            return new PageDTO<>(p.getTotal(), p.getPages(), vos);
        }
    }
    
  4. 查询类继承分页实体类
    @EqualsAndHashCode(callSuper = true)
    @Data
    @ApiModel(description = "用户查询条件实体")
    public class UserQuery extends PageQuery{
        @ApiModelProperty("用户名关键字")
        private String name;
        @ApiModelProperty("用户状态:1-正常,2-冻结")
        private Integer status;
        @ApiModelProperty("余额最小值")
        private Integer minBalance;
        @ApiModelProperty("余额最大值")
        private Integer maxBalance;
    }
    
  5. 实现查询接口
    // Controller
        @ApiOperation("根据条件分页查询用户接口")
        @GetMapping("/page")
        public PageDTO<UserVO> queryUserPage(UserQuery query){
            return userService.queryUsersPage(query);
        }
    // Service
        PageDTO<UserVO> queryUsersPage(UserQuery query);
    // Impl
        @Override
        public PageDTO<UserVO> queryUsersPage(UserQuery query) {
            String name = query.getName();
            Integer status = query.getStatus();
            //  1. 构建查询条件
            //  1.1 分页条件
            Page<User> page = query.toMpPageDefaultSortByUpdateTimeDesc();
            //  2. 分页查询
            Page<User> p = lambdaQuery()
                    .like(name!=null,User::getUsername,name)
                    .eq(status!=null,User::getStatus,status)
                    .page(page);
            //  3. 封装VO结果
            return PageDTO.of(p,user -> {
            //    1. 拷贝基础属性
                UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
            //    2. 处理特殊逻辑
                vo.setUsername(vo.getUsername() +"**");
                return vo;
            });
        }

     最后,

            希望文章对你有所帮助!

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

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

相关文章

禁用layui树形表格的多选框checkbox

1. 背景 在使用树形表格渲染数据时&#xff0c;需要对数据进行批量操作。相对于选中数据后&#xff0c;再做错误提示。直接把数据的多选框禁用掉更加直观。 2. 实现 DisabledTableCheckBox: () > {// 获取所有行 var tableElem $(".layui-table-fixed-l");var …

操作系统教材第6版——个人笔记6

3.3.4 页面调度 页面调度 当主存空间已满而又需要装入新页时&#xff0c;页式虚拟存储管理必须按照一定的算法把已在主存的一些页调出去 #主存满加新&#xff0c;把已在主存一些页调出选择淘汰页的工作称为页面调度 选择淘汰页的算法称为页面调度算法 页面调度算法设计不当&a…

Linux日志服务rsyslog深度解析(上)

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Linux &#xff1a;从菜鸟到飞鸟的逆袭》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、日志在Linux系统中的作用 2、rsyslog历史背景 …

python怎么下载numpy

安装Python step1&#xff1a;官网下载安装包&#xff1b; https://www.python.org/ 我下载的是python-3.4.4.msi step2&#xff1a;python环境变量配置&#xff1b; 计算机-属性-高级系统设置-环境变量-系统变量 找到PATH&#xff0c;点击编辑&#xff0c;加英文分号;在…

【Java面试】十五、HashMap相关

文章目录 1、二叉树1.1 二叉搜索树1.2 红黑树 2、散列表2.1 哈希冲突2.2 哈希冲突 - 链表法 3、HashMap的实现原理4、HashMap源码4.1 属性部分4.2 构造函数部分 5、HashMap的put方法的流程6、HashMap的扩容机制7、HashMap的寻址算法8、为何HashMap底层的数组长度一定是2的次幂 …

个人笔记-python生成gif

使用文件的修改时间戳进行排序 import os import re import imageio# 设置图片所在的文件夹路径 folder_path /home/czy/ACode/AMAW_20240219/9.3.x(Discrete_time_marching&#xff09;/9.3.17.11.1(Disc_concessive_CH_ZJ)/current_figures # 文件夹路径&#xff1b;linux…

Python Virtualenv:创建独立的 Python 开发环境

在当今软件开发的世界中&#xff0c;Python 是一种备受欢迎的编程语言&#xff0c;其简洁、易读和强大的特性吸引了无数开发者。然而&#xff0c;随着项目的增多和复杂度的提高&#xff0c;有效地管理 Python 项目所需的各种依赖项和库变得越来越重要。在这种情况下&#xff0c…

IPv4 和 IPv6 是什么意思?它们之间的区别都有哪些?

什么是 IPv4 和 IPv6 什么是 IPv4 和 IPv6 呢&#xff1f;下面我们就来了解一下。 IPv4 就是互联网协议第 4 版&#xff0c;是目前广泛使用的网络协议版本。它由互联网工程任务组&#xff08;IETF&#xff09;在 1981 年开发完成。IPv4 使用 32 位地址&#xff0c;允许大约 4…

Vue——子级向父级使用props传递数据(函数)

文章目录 前言原理案例效果演示 前言 看到这个标题&#xff0c;相信很多人会说我&#xff0c;你之前博客写的父级向子级中传递数据使用的是props&#xff0c;然后说的子级向父级传递数据则是用的$emit。 并且还说了对于String、数组Array&#xff0c;只能是父级使用props传递…

深度学习_02_卷积神经网络循环神经网络

卷积神经网络 1. 卷积神经网络 神经元存在局部感受区域----感受野 . 第一个卷积神经网络雏形----新认知机 缺点&#xff1a;没有反向传播算法更新权值&#xff0c;模型性能有限 第一个大规模商用卷积神经网络----Lenet-5 缺点&#xff1a;没有大量数据和高性能计算资源。 第一个…

第三篇——大数据思维的科学基础

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 大数据时代&#xff0c;大数据思维的重要性不言而喻&#xff1b;而信息在…

eclipse添加maven插件

打开eclipse菜单 Help/Install New SoftwareWork with下拉菜单选择 2022-03 - https://download.eclipse.org/releases/2022-03‘type filter text’搜索框中输入 maven选择 M2E - Maven Integration for Eclipse一路next安装&#xff0c;重启eclipseImport项目时&#xff0c;就…

教程 | Navicat 17 管理连接新方法

Navicat 17 提供了比以往更多的连接数据库实例的方式。除了传统的连接字符串方式以外&#xff0c;Navicat 17 还支持 URI 连接&#xff0c;无论身在何处&#xff0c;都可以轻松地通过 URI 访问对象。另外&#xff0c;还有一个新的管理连接功能&#xff0c;即允许你通过一个以用…

Pandas读取excel异常

Pandas 处理excel异常: ValueError: Excel file format cannot be determined, you must specify an engine manually.今天使用pandas 处理excel的时候&#xff0c;抛出异常&#xff1a;ValueError: Excel file format cannot be determined, you must specify an engine manua…

【多模态】36、ShareGPT4V | 借助 GPT4V 的能够来生成更丰富的 caption 用于提升 LMM 模型的能力

文章目录 一、背景二、方法2.1 ShareGPT4V 数据集构建2.2 ShareGPT4V-PT 数据生成2.3 ShareGPT4V-7B Model 三、效果3.1 benchmark3.2 定量分析3.3 多模态对话 四、一些例子 论文&#xff1a;ShareGPT4V: Improving Large Multi-Modal Models with Better Captions 代码&#…

PolygonalSurfaceContourLineInterpolator 多边形交互器

1. 效果&#xff1a; 2.简介&#xff1a; 可以实现在多边形上进行交互&#xff0c;选择&#xff1b;在多边形曲面上实现轮廓点的交互绘制。 该类的使用需要结合 vtkPolygonalSurfacePointPlacer 类&#xff0c;定位点的功能也就是拾取器。 前提&#xff1a;输入的多边形曲面…

华为OD机试 - 两个字符串间的最短路径问题 - 动态规划(Java 2024 D卷 200分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;D卷C卷A卷B卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测…

485数据采集模块

在工业自动化与智能化的浪潮中&#xff0c;数据采集作为整个系统的基础和核心&#xff0c;其准确性和实时性直接关系到生产效率和产品质量。而485数据采集模块&#xff0c;作为连接现场设备与上位机的重要桥梁&#xff0c;其性能与稳定性对于整个系统的运行至关重要。HiWoo Box…

GAT1399协议分析(8)--批量图像查询

一、请求消息定义 视频图像包含视频片段、 图像、 文件、 人员、 人脸、 机动车、 非机动车、 物品、 场景和视频案事件、 视频图像标签等对象 在消息体中,可以包含其中一种类,加上Data字段即可。 ImageInfo对象 二、请求消息实例 wireshark 抓包实例 请求: 文本化: /V…

Linux网络编程:数据链路层协议

目录 前言&#xff1a; 1.以太网 1.1.以太网帧格式 1.2.MTU&#xff08;最大传输单元&#xff09; 1.2.1.IP协议和MTU 1.2.2.UDP协议和MTU 1.2.3.TCP协议和MTU 2.ARP协议&#xff08;地址解析协议&#xff09; 2.1.ARP在局域网通信的角色 2.2.ARP报文格式 2.3.ARP报文…