Mybatis-plus从入门到精通

news2024/11/26 12:22:06

1、什么是MyBatis-Plus

MyBatis-Plus(简称MP)是一个基于MyBatis的增强工具,在MyBatis的基础上对其进行扩展,用于简化MyBatis操作,提高开发效率。它继承了MyBatis原生的所有特性,并且添加了一些额外的功能,如自动化代码生成、通用增删改查操作、条件构造器等。MyBatis-Plus是为了满足日常开发中对简单CRUD操作的需求而设计的,它的目标是让开发人员专注于业务逻辑,而不是过多关注底层的数据库操作。

MyBatis-Plus的主要特性包括:

1、 无侵入:MyBatis-Plus只是作为MyBatis的一个插件,不会对MyBatis原有的功能产生影响,可以很容易地与已有的MyBatis项目集成。

2、 通用CRUD操作:MyBatis-Plus提供了一系列通用的CRUD方法,减少了手动编写SQL和Mapper接口的工作量。通过继承BaseMapper接口,你可以使用这些通用方法,从而实现基本的增删改查操作。

3、 条件构造器:MyBatis-Plus提供了一个强大的条件构造器,用于生成复杂的SQL查询条件。这个条件构造器使得编写查询语句更加简洁、易读。

4、 分页插件:MyBatis-Plus内置了一个功能强大的分页插件,支持多种数据库的分页查询。开发人员无需手动编写分页SQL,只需简单地调用API即可实现分页功能。

5、 代码生成器:MyBatis-Plus提供了一个自动化的代码生成器,可以快速生成实体类、Mapper接口、Service接口和实现类、Controller类等。这极大地提高了开发效率,减少了手动编写重复代码的工作量。

6、 性能优化:MyBatis-Plus针对一些常见的性能问题进行了优化,例如SQL注入攻击防护、缓存优化等。

总之,MyBatis-Plus是一个强大的MyBatis增强工具,它继承了MyBatis的所有特性,并且提供了一些额外的功能,以提高开发效率和简化CRUD操作。如果你已经在使用MyBatis,那么MyBatis-Plus将是一个非常值得尝试的工具。

官网地址
https://www.baomidou.com/

2、快速入门

2.1、Maven依赖 (pom.xml)

请将以下依赖项添加到项目的pom.xml文件中:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.3.3</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.20</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

2.2、application.yml配置文件

以下是一个简单的application.yml配置文件示例,包含了MyBatis-Plus和MySQL数据库的配置:

server:
  port: 8080

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis_demo?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: your_username
    password: your_password

mybatis-plus:
  mapper-locations: classpath*:/mapper/**/*.xml
  type-aliases-package: com.example.demo.entity
  configuration: 
  	log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志
  global-config:
    db-config:
      id-type: auto

logging:
  level:
    root: info

在这个配置文件中,我们设置了服务器的端口号、数据源的驱动程序类名、数据库URL、用户名和密码。我们还配置了MyBatis-Plus的映射文件位置、类型别名包和全局配置,其中包括数据库ID自动生成策略。

2.3、MySQL建表语句和初始化数据

CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO `user` (`id`, `name`, `age`, `email`) VALUES
(1, 'Tom', 28, 'tom@example.com'),
(2, 'Jerry', 29, 'jerry@example.com'),
(3, 'Spike', 30, 'spike@example.com');

2.4、实体类 (User.java)

package com.example.demo.entity;

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

@Data
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

2.5、Mapper接口 (UserMapper.java)

package com.example.demo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

2.6、Service接口 (UserService.java)

package com.example.demo.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.entity.User;

public interface UserService extends IService<User> {
}

2.7、Service实现类 (UserServiceImpl.java)

package com.example.demo.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;

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

2.8、Controller类 (UserController.java)

package com.example.demo.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping
    public User createUser(@RequestBody User user) {
        userService.save(user);
        return user;
    }

    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.getById(id);
    }

    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        user.setId(id);
        userService.updateById(user);
        return user;
    }

    @DeleteMapping("/{id}")
    public String deleteUser(@PathVariable Long id) {
        userService.removeById(id);
        return "User with ID " + id + " has been deleted.";
    }

    @GetMapping("/list")
    public List<User> listUsers() {
        return userService.list();
    }

    @GetMapping("/page")
    public IPage<User> pageUsers(@RequestParam(defaultValue = "1") int current,
                                  @RequestParam(defaultValue = "10") int size) {
        Page<User> userPage = new Page<>(current, size);
        return userService.page(userPage);
    }
}

上面的代码展示了基于MyBatis-Plus的增删改查示例。UserController类定义了创建、获取、更新、删除用户和分页查询的RESTful接口。具体来说,createUser、getUser、updateUser、deleteUser、listUsers和pageUsers方法分别负责创建用户、根据ID获取用户、更新用户、删除用户、列出所有用户和分页查询用户。这些方法都依赖于注入的UserService实现类。

现在,你可以运行你的Spring Boot应用程序并通过RESTful API进行增删改查操作。

3、@TableId及主键策略

@TableId注解用于指定数据库表的主键字段。这个注解可以放在实体类的字段上,以便MyBatis-Plus能识别哪个字段是数据库表的主键。

@TableId注解有一个属性type,它代表了主键策略。MyBatis-Plus支持以下几种主键策略:

1、 IdType.AUTO:数据库ID自增。这是默认的主键策略,适用于MySQL、PostgreSQL等支持自增主键的数据库。在插入数据时,主键字段的值由数据库自动生成。

2、 IdType.NONE:无主键策略。如果你的表没有主键,可以使用这个选项。此时,插入数据时需要手动为主键字段设置值。

3、 IdType.INPUT:手动输入。这种策略适用于那些需要手动为主键字段设置值的场景。在插入数据时,需要为主键字段提供一个值,否则会引发异常。

4、 IdType.UUID:全局唯一ID。在这种策略下,MyBatis-Plus会自动为主键字段生成一个UUID值。这种策略适用于那些需要全局唯一ID的场景,如分布式系统。

5、 IdType.ID_WORKER:分布式唯一ID。这种策略使用MyBatis-Plus内置的雪花算法(Snowflake Algorithm)生成分布式唯一ID。这个算法保证了在分布式环境中生成的ID是唯一的。

6、 IdType.ID_WORKER_STR:分布式唯一ID字符串。与IdType.ID_WORKER类似,但生成的ID会转换为字符串格式。

7、 IdType.ASSIGN_ID:分配ID。这种策略使用MyBatis-Plus内置的ID生成器生成一个64位整数作为主键。生成的ID是全局唯一的,适用于分布式场景。

8、 IdType.ASSIGN_UUID:分配UUID。与IdType.UUID类似,但使用MyBatis-Plus内置的ID生成器生成UUID。

要自定义主键策略,你需要实现IdentifierGenerator接口,并在@TableId注解中指定自定义的实现类。以下是一个自定义主键策略的示例:

public class CustomIdGenerator implements IdentifierGenerator {

    @Override
    public Number nextId(Object entity) {
        // 实现你的自定义主键生成逻辑
        return yourCustomGeneratedId;
    }

    @Override
    public String nextUUID(Object entity) {
        // 实现你的自定义UUID生成逻辑
        return yourCustomGeneratedUuid;
    }
}

然后,在实体类的主键字段上使用@TableId注解,并指定type为IdType.ASSIGN_ID或IdType.ASSIGN_UUID:

@TableId(value ="value", type = IdType.ASSIGN_ID, generator = "com.example.demo.CustomIdGenerator")
private Long id;

在这个例子中,我们为主键字段id指定了IdType.ASSIGN_ID策略,并提供了自定义的CustomIdGenerator类来生成主键值。当插入新数据时,MyBatis-Plus将使用CustomIdGenerator提供的主键值。同样,如果你想使用自定义的UUID生成策略,只需将type属性更改为IdType.ASSIGN_UUID即可。

这样,你就可以根据自己的需求自定义主键策略,并在实体类中使用@TableId注解来指定该策略。

4、自动填充数据

MyBatis-Plus中的自动填充功能允许你在插入和更新操作中自动填充某些字段,例如创建时间、更新时间等。要实现自动填充功能,你需要创建一个类实现MetaObjectHandler接口,然后在实体类中使用@TableField注解指定要自动填充的字段。

MetaObjectHandler接口定义了两个方法:insertFill和updateFill。insertFill方法用于在插入操作中自动填充字段,updateFill方法用于在更新操作中自动填充字段。以下是一个实现MetaObjectHandler接口的示例:

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
        this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
    }
}

在这个例子中,我们创建了一个名为MyMetaObjectHandler的类,并实现了insertFill和updateFill方法。在insertFill方法中,我们使用strictInsertFill方法指定在插入操作时自动填充createTime和updateTime字段。在updateFill方法中,我们使用strictUpdateFill方法指定在更新操作时自动填充updateTime字段。

接下来,在实体类中使用@TableField注解指定要自动填充的字段:

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import java.time.LocalDateTime;

public class User {

    // ...其他字段

    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    @TableField(fill = FieldFill.UPDATE)
    private LocalDateTime updateTime;

    // ...getter和setter方法
}

在这个例子中,我们为createTime字段指定了FieldFill.INSERT填充类型,这意味着在插入操作时将自动填充该字段。我们为updateTime字段指定了FieldFill.UPDATE填充类型,这意味着在更新操作时将自动填充该字段。

除了FieldFill.INSERT和FieldFill.UPDATE填充类型,MyBatis-Plus还支持以下填充类型:

1、 FieldFill.DEFAULT:默认填充类型,不进行自动填充。 2、 FieldFill.INSERT_UPDATE:在插入和更新操作中自动填充字段。

要使用FieldFill.INSERT_UPDATE填充类型,只需将@TableField注解的fill属性设置为FieldFill.INSERT_UPDATE即可。例如:

@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime someField;

这样,在插入和更新操作中,MyBatis-Plus将自动填充someField字段。

总结一下,MyBatis-Plus的自动填充功能允许你在插入和更新操作中自动填充指定字段,如创建时间、更新时间等。要使用自动填充功能,你需要:

1、 创建一个实现MetaObjectHandler接口的类,并重写insertFill和updateFill方法。 2、 在实体类中,使用@TableField注解指定要自动填充的字段,并设置相应的填充类型(FieldFill.DEFAULT、FieldFill.INSERT、FieldFill.UPDATE或FieldFill.INSERT_UPDATE)。

这样,MyBatis-Plus就会根据指定的填充类型在插入和更新操作中自动填充相应字段。

5、乐观锁插件

乐观锁插件是MyBatis-Plus中的一个功能,用于在并发场景下保证数据的一致性。乐观锁插件通过在更新操作时增加版本号或者其他标识,以确保在多个线程同时更新同一条记录时,只有一个线程能够成功执行更新。

以下是使用MyBatis-Plus乐观锁插件的示例:

5.1、首先,我们需要在Spring Boot配置类中注入乐观锁插件:

import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan("按需修改")
public class MybatisPlusConfig {

    /**
     * 旧版
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }

    /**
     * 新版
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

在这个例子中,我们创建了一个名为MybatisPlusConfig的配置类,并定义了一个
optimisticLockerInterceptor Bean。这样,乐观锁插件就会被自动添加到MyBatis-Plus中。

5.2、接下来,在实体类中为某个字段添加@Version注解,以表示这个字段用于存储版本信息。通常,这个字段是一个整数或者长整数类型,用于记录数据的修改次数。

import com.baomidou.mybatisplus.annotation.Version;
import java.io.Serializable;

public class User implements Serializable {

    // ...其他字段

    @Version
    private Integer version;

    // ...getter和setter方法
}

在这个例子中,我们为version字段添加了@Version注解,表示这个字段将用于存储版本信息。

5.3、现在,你可以正常地执行更新操作。当使用MyBatis-Plus的更新方法时,乐观锁插件会自动处理版本号的递增和校验。

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public void updateUser(Long userId, String newName) {
        User user = userMapper.selectById(userId);
        user.setName(newName);
        userMapper.updateById(user);
    }
}

在这个例子中,我们创建了一个UserService类,并定义了一个updateUser方法。这个方法首先根据ID查询用户,然后修改用户的名称,并调用userMapper.updateById(user)方法执行更新操作。在这个过程中,乐观锁插件会自动处理版本号的递增和校验。

这样,通过使用MyBatis-Plus的乐观锁插件,你可以在并发场景下保证数据的一致性。只需简单地在实体类中添加@Version注解并注入乐观锁插件,即可实现这个功能。

6、其他插件(如:逻辑删除、分页查看...)查看官网

官网地址
https://www.baomidou.com/

7、增删改查常用方法

MyBatis-Plus提供了一系列常用的增删改查方法,大大简化了对数据库表的操作。以下是一些常用方法的介绍:

7.1、插入(Insert)

  • int insert(T entity):插入一条记录。传入的实体类对象entity中的非空字段会被插入到数据库表中。返回值为受影响的行数。

7.2、删除(Delete)

  • int deleteById(Serializable id):根据主键ID删除一条记录。返回值为受影响的行数。
  • int delete(Wrapper<T> queryWrapper):根据条件删除记录。queryWrapper为查询条件。返回值为受影响的行数。
  • int deleteBatchIds(Collection<? extends Serializable> idList):根据主键ID批量删除记录。idList为主键ID集合。返回值为受影响的行数。

7.3、更新(Update)

  • int updateById(T entity):根据主键ID更新一条记录。传入的实体类对象entity中的非空字段会被更新到数据库表中。返回值为受影响的行数。
  • int update(T entity, Wrapper<T> updateWrapper):根据条件更新记录。entity为要更新的字段值,updateWrapper为更新条件。返回值为受影响的行数。

7.4、查询(Select)

  • T selectById(Serializable id):根据主键ID查询一条记录。返回查询到的记录对象。
  • List<T> selectBatchIds(Collection<? extends Serializable> idList):根据主键ID批量查询记录。idList为主键ID集合。返回查询到的记录列表。
  • List<T> selectList(Wrapper<T> queryWrapper):根据条件查询记录列表。queryWrapper为查询条件。返回查询到的记录列表。
  • List<Map<String, Object>> selectMaps(Wrapper<T> queryWrapper):根据条件查询记录,并将结果转换为Map列表。queryWrapper为查询条件。返回查询到的记录列表,每个记录为一个Map对象。
  • T selectOne(Wrapper<T> queryWrapper):根据条件查询一条记录。queryWrapper为查询条件。返回查询到的记录对象。注意:当查询结果多于一条时,该方法会抛出异常。
  • int selectCount(Wrapper<T> queryWrapper):根据条件查询记录数量。queryWrapper为查询条件。返回查询到的记录数量。

这些方法都是基于MyBatis-Plus提供的BaseMapper<T>接口定义的,你只需要在你的Mapper接口中继承BaseMapper<T>,即可使用这些方法。例如:

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.User;

public interface UserMapper extends BaseMapper<User> {
}

8、条件构造器Wrapper(常用)

MyBatis-Plus中的条件构造器Wrapper(如QueryWrapper<T>和UpdateWrapper<T>)提供了一系列常用的条件构造方法,帮助你轻松构建复杂的查询和更新条件。以下是一些常用方法的介绍:

8.1、基本条件

  • eq(String column, Object val):等于,用于构造“column = val”的条件。
  • ne(String column, Object val):不等于,用于构造“column <> val”的条件。
  • gt(String column, Object val):大于,用于构造“column > val”的条件。
  • ge(String column, Object val):大于等于,用于构造“column >= val”的条件。
  • lt(String column, Object val):小于,用于构造“column < val”的条件。
  • le(String column, Object val):小于等于,用于构造“column <= val”的条件。
  • between(String column, Object val1, Object val2):范围,用于构造“column BETWEEN val1 AND val2”的条件。
  • notBetween(String column, Object val1, Object val2):非范围,用于构造“column NOT BETWEEN val1 AND val2”的条件。
  • like(String column, Object val):模糊查询,用于构造“column LIKE %val%”的条件。
  • notLike(String column, Object val):非模糊查询,用于构造“column NOT LIKE %val%”的条件。

8.2、常用条件组合

  • and(String sql):与,用于连接两个条件,如“condition1 AND condition2”。
  • or(String sql):或,用于连接两个条件,如“condition1 OR condition2”。

8.3、嵌套条件

  • and(Consumer<Param> consumer):与,用于构造嵌套条件,如“condition1 AND (condition2 OR condition3)”。
  • or(Consumer<Param> consumer):或,用于构造嵌套条件,如“condition1 OR (condition2 AND condition3)”。

8.4、排序

  • orderByAsc(String... columns):升序排序,用于构造“ORDER BY column1 ASC, column2 ASC”等排序条件。
  • orderByDesc(String... columns):降序排序,用于构造“ORDER BY column1 DESC, column2 DESC”等排序条件。

以下是一个使用条件构造器Wrapper的查询示例:

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {
    @Autowired
private UserMapper userMapper;

public List<User> getUsersByNameAndAge(String name, Integer minAge, Integer maxAge) {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.like("name", name)
                .ge("age", minAge)
                .le("age", maxAge)
                .orderByAsc("age");
    
    return userMapper.selectList(queryWrapper);
	}
}

在这个示例中,我们创建了一个UserService类,并实现了一个getUsersByNameAndAge方法。这个方法使用QueryWrapper构造了一个查询条件,用于查找名字包含name,年龄在minAge和maxAge之间并按年龄升序排列的用户。通过调用userMapper.selectList(queryWrapper),我们可以获取符合条件的用户列表。

总之,MyBatis-Plus中的条件构造器Wrapper提供了一系列常用的条件构造方法,帮助你轻松构建复杂的查询和更新条件。通过使用QueryWrapper和UpdateWrapper,你可以方便地构造各种条件,并将这些条件应用到MyBatis-Plus的增删改查方法中。

 

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

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

相关文章

《TCP IP网络编程》第十章

第 10 章 多进程服务器端 10.1 进程概念及应用 并发服务端的实现方法&#xff1a; 通过改进服务端&#xff0c;使其同时向所有发起请求的客户端提供服务&#xff0c;以提高平均满意度。而且&#xff0c;网络程序中数据通信时间比 CPU 运算时间占比更大&#xff0c;因此&#…

探析国内数字孪生引擎技术现状

在数字孪生软件来发中&#xff0c;渲染引擎是一个关键点&#xff0c;国内大多数字孪生平台引擎通常使用的是自研的渲染引擎或者采用开源的渲染引擎。下面通过一些常见的渲染引擎在国内数字孪生引擎中的应用带大家了解数字孪生软件开发的方式。 自研渲染引擎&#xff1a;许多数…

CNN + Vision Transformer 结合学习

介绍三篇结合使用CNNTransformer进行学习的论文&#xff1a;CvT&#xff08;ICCV2021&#xff09;&#xff0c;Mobile-Former&#xff08;CVPR2022&#xff09;&#xff0c;SegNetr&#xff08;arXiv2307&#xff09;. CvT: Introducing Convolutions to Vision Transformers, …

利用 trait 实现多态

我在书上看到基于 std::io::Write 的示例&#xff0c;它是一个 trait 类型&#xff0c;内部声明了一些方法。和 go 语言不同&#xff0c;rust 中类型必须明确实现 trait 类型&#xff0c;而 go 语言属于 duck 模式。 std::io::Write下面的例子中调用 write_all 方式来演示&…

标签是系列色并且加粗帆软

标签是系列色并且加粗 function(){return <span style"color:this.color;">FR.contentFormat(this.value, #,##0)</span>;}

UI 自动化的 PageObject 设计模式

目录 前言&#xff1a; 什么是 PageObject 模型&#xff1f; 为什么使用 PageObject 模型&#xff1f; PO 模式优点 PageObject 实践 前言&#xff1a; UI 自动化是一种软件测试方法&#xff0c;它主要用于检查应用程序的用户界面是否符合预期。PageObject 是 UI 自动化中…

AI大模型时代下运维开发探索第一篇:ReAct工程初探

引子 人工智能大模型的出现&#xff0c;已渐渐地影响了我们的日常生活和工作方式。生活中无处不在的AI&#xff0c;使我们的生活变得更加智能和便捷。工作中&#xff0c;AI大模型的高效和精准&#xff0c;极大地提升了我们解决问题的效率。 是的&#xff0c;我们不能忽视AI大…

Delphi 开发者,显示图片请忘掉VCL中的 TImage 吧

目录 序言 使用TImageCollection和TVirtualImageList组件支持高分辨率图像 一、总览 二、使用图像收集组件TImageCollection 2.1 图像收集组件编辑器 2.2 将现有 TImageList 载入 TImageCollection 三、使用Virtual ImageList 组件 3.1 Virtual ImageList Component 编辑…

【数据结构】| 王道考研——树的前世今生

目录 一. &#x1f981; 前言二. &#x1f981; 各种树的知识点1. 树1.1 概念1.2 属性1.3 常考性质1.4 树转换成二叉树1.5 森林转换为二叉树1.6 二叉树转换为森林1.7 树的遍历1.8 森林的遍历 2. 二叉树2.1满二叉树2.2 完全二叉树2.3二叉排序树2.4 平衡二叉树2.5 二叉树常考性质…

IDEA使用lombok实体类加上@Data注解后无法找到get和set方法

文章目录 一、问题原因二、解决方法1.File→Settings2.Plugins→搜索"lombok"→Install3.Restart IDE&#xff08;重启IDEA&#xff09; 一、问题原因 IDEA没有安装lombok插件 二、解决方法 1.File→Settings 2.Plugins→搜索"lombok"→Install 3.Restart…

北斗定位导航系统,北斗模块应用领域发展概况_北斗二号模块,北斗三号模块

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、北斗系统概述1.1 空间段1.2 地面控制段1.3 用户段1.4 坐标系统1.5 时间系统 二、北斗系统定位导航授时服务2.1 服务概述2.2 服务区2.3 北斗信号频段2.4 北斗…

服务器中了Locked勒索病毒怎么解决,勒索病毒解密恢复方式与防护措施

服务器是企业重要数据存储和处理的关键设备&#xff0c;然而&#xff0c;众所周知&#xff0c;服务器系统并非完全免受网络攻击的。其中一种常见的威胁是勒索病毒&#xff0c;其中一种恶名昭彰的变种是Locked勒索病毒。Locked勒索病毒采用了对称AES与非对称RSA的加密形式&#…

【C++入门到精通】C++入门 —— 引用、内联函数

目录 一、引用 1.引用的概念 2.引用的特性 3.常引用 4.引用的使用场景 ⭕做参数 ⭕做返回值 5.传值、传引用效率比较 值和引用的作为返回值类型的性能比较 6.引用和指针的区别 引用和指针的不同点 二、内联函数 1.内联函数的概念 2.内联函数的特性 3.宏与内联函数 …

RocketMQ教程-(5)-功能特性-顺序消息

顺序消息为 Apache RocketMQ 中的高级特性消息&#xff0c;本文为您介绍顺序消息的应用场景、功能原理、使用限制、使用方法和使用建议。 应用场景​ 在有序事件处理、撮合交易、数据实时增量同步等场景下&#xff0c;异构系统间需要维持强一致的状态同步&#xff0c;上游的事…

13.4.2 【Linux】sudo

相对于 su 需要了解新切换的使用者密码 &#xff08;常常是需要 root 的密码&#xff09;&#xff0c; sudo 的执行则仅需要自己的密码即可。sudo 可以让你以其他用户的身份执行指令 &#xff08;通常是使用 root 的身份来执行指令&#xff09;&#xff0c;因此并非所有人都能够…

Spring 多数据源方法级别注解实现

Spring框架提供了多种数据源管理方式&#xff0c;其中多数据源管理是其中之一。多数据源管理允许应用程序使用多个数据源&#xff0c;而不是只使用一个数据源&#xff0c;从而提高了应用程序的灵活性和可靠性。 多数据源管理的主要目的是让应用程序能够在不同的数据库之间切换&…

SpringCache 框架使用以及序列化和缓存过期时间问题的解决

目录 为什么使用Spring Cache 如何使用Spring Cache 1 加依赖 2 开启缓存 3 加缓存注解 序列化以及过期时间等问题 解决方案&#xff1a;自定义序列化方式 1.自定义序列化方式并设置白名单 2.配置并设置缓存的过期时间 为什么使用Spring Cache 缓存有诸多的好处&#x…

YOLOv5(v7.0)网络修改实践二:把单分支head改为YOLOX的双分支解耦合head(DecoupleHead)

前面研究了一下YOLOX的网络结构&#xff0c;在YOLOv5(tag7.0)集成了yolox的骨干网络&#xff0c;现在继续下一步集成YOLOX的head模块。YOLOX的head模块是双分支解耦合网络&#xff0c;把目标置信度的预测和目标的位置预测分成两条支路&#xff0c;并验证双分支解耦合头性能要优…

为什么视频画质会变差,如何提升视频画质清晰度。

在数字时代&#xff0c;视频已经成为我们生活中不可或缺的一部分。然而&#xff0c;随着视频的传输和处理过程中的多次压缩&#xff0c;画质损失逐渐凸显&#xff0c;影响了我们对影像的真实感受。为了让视频画质更加清晰、逼真&#xff0c;我们需要采取一些措施来保护和修复视…

设计模式大白话——观察者模式

文章目录 一、概述二、示例三、模式定义四、其他 一、概述 ​ 与其叫他观察者模式&#xff0c;我更愿意叫他叫 订阅-发布模式 &#xff0c;这种模式在我们生活中非常常见&#xff0c;比如&#xff1a;追番了某个电视剧&#xff0c;当电视剧有更新的时候会第一时间通知你。当你…