数据持久层框架:MyBatis-Plus

数据持久层框架:MyBatis-Plus

  • 前言
    • 注解
    • 代码生成器
    • CURD接口
      • Service CRUD 接口
      • Mapper CRUD 接口
    • 条件构造器
      • QueryWrapper和UpdateWrapper
      • allEq
      • eq、ne
      • gt、ge、lt、le
      • between、notBetween
      • like、notLike、likeLeft、likeRight、notLikeLeft、notLikeRight
      • isNull、isNotNull
      • in、notIn、inSql、notInSql
      • groupBy、orderByAsc、orderByDesc、having
      • or、and
      • exists、notExists
      • 组合查询
      • 动态条件查询
    • 主键策略
    • 逻辑删除
    • 自动填充功能
    • 防全表更新与删除插件
    • MybatisX快速开发插件

前言

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 MapperModelServiceController 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 deleteupdate 操作智能分析阻断,也可自定义拦截规则,预防误操作

SpringBoot为例,导入依赖:

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.5</version>
</dependency>

数据库配置如下

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring_data?characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456

示例代码如下:

@TableName("user")
public class User {private Integer id;private String name;private String age;//getter and setter
}
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
@SpringBootApplication
@MapperScan("com.example.mybatisstudy.dao")//扫描mapper
public class MybatisStudyApplication {public static void main(String[] args) {SpringApplication.run(MybatisStudyApplication.class, args);}}
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test {@Autowiredprivate UserMapper userMapper;@org.junit.Testpublic void testSelect() {System.out.println(("----- selectAll method test ------"));List<User> userList = userMapper.selectList(null);userList.forEach(System.out::println);}
}

效果如图
在这里插入图片描述
从以上步骤中,我们可以看到集成MyBatis-Plus非常的简单,只需要引入 starter 工程,并配置 mapper 扫描路径即可。甚至连 XML 文件都不用编写!

注解

  • @TableName:表名注解,标识实体类对应的表
@TableName("user")
public class User {private Integer id;private String name;private String age;//getter and setter
}

注解更多属性如图:
在这里插入图片描述

  • @TableId:主键注解
@TableName("user")
public class User {@TableId(value = "id",type = IdType.AUTO)private Integer id;
}

types属性指定主键类型,默认IdType.NONE
在这里插入图片描述

  • @TableField:字段注解(非主键)
@TableName("user")
public class User {@TableId(value = "id",type = IdType.AUTO)private Integer id;@TableField(value = "name")private String name;
}

注解更多属性如图:
在这里插入图片描述

  • @Version:乐观锁注解、标记在字段上。
@TableName("user")
public class User {@TableId(value = "id",type = IdType.AUTO)@Versionprivate Integer id;
}

然后注册Bean

@Configuration
public class MyConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return mybatisPlusInterceptor;}
}
  • @EnumValue:普通枚举类注解。
@TableName("user")
public class User {@TableId(value = "id",type = IdType.AUTO)@Versionprivate Integer id;@EnumValueprivate String type;
}
  • @TableLogic:表字段逻辑处理注解(逻辑删除)。
@TableName("user")
public class User {@TableId(value = "id",type = IdType.AUTO)private Integer id;@TableField(value = "name")@TableLogic(value = "a",delval = "b")private String name;
}

value属性表示逻辑未删除值,delval属性表示逻辑删除值。

  • @KeySequence:于指定插入操作返回自增主键值的注解。在 MyBatis 中,有些数据库(如 Oracle)并不是像 MySQL 那样具有自增长主键的功能,而是通过序列(sequence)来生成主键值。
@TableName("user")
@KeySequence(value = "id",dbType = DbType.MYSQL)
public class User {
}
  • @InterceptorIgnore:用于指定是否在某个方法上忽略拦截器的注解。
@Intercepts({@Signature(type= Executor.class,method = "update",args = {MappedStatement.class,Object.class})
})
public class ExampleInterceptor implements Interceptor {// 实现拦截器的逻辑// ...
}public interface UserMapper {@InterceptorIgnore@Insert("INSERT INTO users (id, name) VALUES (#{id}, #{name})")int insertUser(User user);}
  • @OrderBy:指定查询操作的结果集的排序规则。
@TableName("user")
public class User {@TableId(value = "id", type = IdType.AUTO)private Integer id;@TableField(value = "name")private String name;@OrderBy(asc = true)private String age;
}

代码生成器

引入依赖

        <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.5</version></dependency><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.0</version></dependency>

示例代码如下:

public class Test {public static void main(String[] args) {FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/spring_data", "root", "123456")// 全局配置.globalConfig((scanner, builder) -> {builder.author(scanner.apply("请输入作者名称?"));// 获取用户的当前工作目录String userDir = System.getProperty("user.dir");builder.outputDir(userDir+"\\src\\main\\java\\"); // 指定输出目录})// 包配置.packageConfig((scanner, builder) -> builder.parent(scanner.apply("请输入包名?")))// 策略配置.strategyConfig((scanner, builder) -> builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all"))).controllerBuilder().enableRestStyle().enableHyphenStyle().entityBuilder().enableLombok().addTableFills(new Column("create_time", FieldFill.INSERT)).build())/*模板引擎配置,默认 Velocity 可选模板引擎 Beetl 或 Freemarker.templateEngine(new BeetlTemplateEngine()).templateEngine(new FreemarkerTemplateEngine())*/.execute();}// 处理 all 情况protected static List<String> getTables(String tables){return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));}}

改进后,会自动生成到当前项目中,如图所示
在这里插入图片描述

CURD接口

Service CRUD 接口

Service CRUD 封装IService (opens new window)接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆,

public interface IUserService extends IService<User> {
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}
  • Save

数据插入,如果数据已存在则报错

// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量),batchSize:插入批次数量
boolean saveBatch(Collection<T> entityList, int batchSize);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(9);user.setName("f");user.setAge("23");boolean b = iUserService.save(user);System.out.println(b);/** Output*  true*/}
}
  • SaveOrUpdate

先查询,数据库存在则更新记录,否插入一条记录

// TableId 注解存在更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新(类似条件)
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(6);user.setName("f");user.setAge("23");boolean b = iUserService.saveOrUpdate(user);User user2 = new User();user2.setId(8);user2.setName("g");user2.setAge("23");boolean b2 = iUserService.saveOrUpdate(user2);}
}

如图所示:
在这里插入图片描述

  • Remove

数据删除

// 根据 queryWrapper 设置的条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){boolean b = iUserService.removeById(7);boolean b2 = iUserService.removeByIds(Arrays.asList(1,2,3,4));}
}
  • Update

数据更新

// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereWrapper 条件,更新记录
boolean update(T updateEntity, Wrapper<T> whereWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(6);user.setName("f");user.setAge("23");boolean b = iUserService.updateById(user);System.out.println(b);/** Output*  true*/}
}
  • Get

获取单条数据

// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){User user = iUserService.getById(1);System.out.println(user.toString());/** Output*  {id:1,name:a,age:12}*/}
}
  • List

获取列表数据

// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查询所有列表
List<Map<String, Object>> listMaps();
// 查询列表
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录
List<Object> listObjs();
// 查询全部记录
<V> List<V> listObjs(Function<? super Object, V> mapper);
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){List<User> list = iUserService.list();System.out.println(list.toString());System.out.println("===========================");Map<String, Object> map= new HashMap<>();map.put("name","a");List<User> list2 = iUserService.listByMap(map);System.out.println(list2.toString());System.out.println("===========================");List<User> list3 = iUserService.listByIds(Arrays.asList(1,2,3,4));System.out.println(list3.toString());/** Output*  [{id:1,name:a,age:12}, {id:2,name:b,age:13}, {id:3,name:c,age:14}, {id:4,name:bb,age:15}, {id:5,name:ee,age:22}, {id:6,name:null,age:2}, {id:7,name:f,age:2}]*  ===========================*  [{id:1,name:a,age:12}]*  ===========================*  [{id:1,name:a,age:12}, {id:2,name:b,age:13}, {id:3,name:c,age:14}, {id:4,name:bb,age:15}]*/}
}
  • Page

你需要配置分页拦截器:

@Configuration
public class MyConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return mybatisPlusInterceptor;}
}

调用page()方法进行分页

// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);

Page对象一共有四个构造方法,可以用来定义分页的页数和条数,你也可以调用对应的set方法进行赋值。

//传入页数、条数
public Page(long current, long size) {}
//传入页数、条数、总数
public Page(long current, long size, long total) {}
//传入页数、条数、是否查询总数:true是、false否
public Page(long current, long size, boolean searchCount) {}
//传入页数、条数、总数、是否查询总数:true是、false否
public Page(long current, long size, long total, boolean searchCount) {}

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){Page<User> userPage = new Page<>(1,3,true);Page<User> p = iUserService.page(userPage);List<User> records = p.getRecords();System.out.println(records.toString());/** Output*  [{id:1,name:a,age:12}, {id:2,name:b,age:13}, {id:3,name:c,age:14}]*/}
}

searchCount属性为true的情况,会先去查询总数后分页。

在这里插入图片描述

  • Count

查询总数

// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){long count = iUserService.count();System.out.println(count);/** Output*  8*/}
}

关于Wrapper对象的使用在稍后的章节里详细讲解。

  • Model

实体类只需继承 Model 类即可进行强大的 CRUD 操作

class User extends Model<User>{// fields...public static void main(String[] args) {User user = new User();user.insert();user.selectAll();user.updateById();user.deleteById();// ...}
}

不过在开发过程中,业务逻辑通过自动注入进行操作,实体类只用于数据传输操作。

Mapper CRUD 接口

通过封装BaseMapper (opens new window)接口实现CRUD操作。

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

新增数据

int insert(T entity);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(10);user.setName("h");user.setAge("23");long insert = userMapper.insert(user);System.out.println(insert);/** Output*  1*/}
}
  • Delete

删除数据

// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){//根据ID删除int deleteById = userMapper.deleteById(1);//根据ID批量删除int deleteById2 = userMapper.deleteBatchIds(Arrays.asList(1, 2, 3, 4));//根据key=value当做条件删除Map<String,Object> map = new HashMap<>();map.put("name","g");int deleteById3 = userMapper.deleteByMap(map);}
}
  • Update

修改数据

// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(10);user.setName("h");user.setAge("23");long insert = userMapper.updateById(user);}
}
  • Select

查询数据

// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 查询(根据ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){//传null查询全部List<User> users = userMapper.selectList(null);//通过id查询User user = userMapper.selectById(1);//批量id查询List<User> users2 = userMapper.selectBatchIds(Arrays.asList(1,2,3,4));//根据key=value当做条件查询Map<String,Object> map = new HashMap<>();map.put("name","g");map.put("age","23");List<User> users3 = userMapper.selectByMap(map);}
}

条件构造器

CRUD的方法中,看到很多的Wrapper参数,下面就来学习如何使用它当中参数。

QueryWrapper和UpdateWrapper

QueryWrapper(LambdaQueryWrapper)UpdateWrapper(LambdaUpdateWrapper) 的父类,用于生成 sqlwhere 条件, entity 属性也用于生成 sqlwhere 条件。

  • QueryWrapper

QueryWrapperMyBatis-Plus 中的一个查询条件构造器,用于构建查询条件。使用 QueryWrapper 可以实现复杂的查询条件组合,例如等值条件、范围条件、模糊查询、排序等。QueryWrapper 还支持 Lambda 表达式,可以通过 Lambda 来指定字段名,减少因为字段改名而引起的错误。

使用select方法,指定查询返回字段。

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.select("id","name");List<User> users = userMapper.selectList(wrapper);}
}

如图所示
在这里插入图片描述

  • UpdateWrapper

UpdateWrapperMyBatis-Plus 中用于构建更新操作条件的类,使用set()方法设置要更新的字段及对应的数值。

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){UpdateWrapper<User> wrapper = new UpdateWrapper<>();wrapper.eq("id","7");wrapper.set("name","g");wrapper.set("age","20");int users = userMapper.update(wrapper);}
}

如图所示
在这里插入图片描述

allEq

传入Map参数,key为数据库字段名,value为字段值。

allEq(Map<R, V> params)
//null2IsNull:忽略空值
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)

示例代码如下:

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){Map<String,Object> map = new HashMap<>();map.put("name","a");map.put("age",null);QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.allEq(map);List<User> users = userMapper.selectList(wrapper);System.out.println(users.toString());wrapper = new QueryWrapper<>();wrapper.allEq(map,false);List<User> users2 = userMapper.selectList(wrapper);System.out.println(users2.toString());/** Output*  []*  [{id:1,name:a,age:12}]*/}
}

执行结果如图

在这里插入图片描述

eq、ne

  • eq:等于 =
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("name","a");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图所示
在这里插入图片描述

  • ne:不等于 <>
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.ne("name","a");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图所示

在这里插入图片描述

gt、ge、lt、le

  • gt:大于 >
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.gt("age",21);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • ge:大于等于 >=
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.ge("age",21);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • lt:小于 <
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.lt("age",21);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • le:小于等于 <=
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.le("age",21);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

between、notBetween

  • between:区间BETWEEN 值1 AND 值2
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.between("age",21,25);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • notBetween:非区间NOT BETWEEN 值1 AND 值2
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notBetween("age",21,25);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图

在这里插入图片描述

like、notLike、likeLeft、likeRight、notLikeLeft、notLikeRight

  • like:全模糊匹配LIKE '%值%'
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.like("name","b");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • notLike:全模糊不匹配NOT LIKE '%值%'
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notLike("name","b");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • likeLeft:左模糊匹配LIKE '%值'
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.likeLeft("name","b");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • likeRight:右模糊匹配LIKE '值%'
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.likeRight("name","b");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • notLikeLeft:左模糊不匹配NOT LIKE '%值'
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notLikeLeft("name","b");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • notLikeRight:右模糊不匹配NOT LIKE '值%'
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notLikeRight("name","b");List<User> users14 = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

isNull、isNotNull

  • isNull:是null
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.isNull("name");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图

在这里插入图片描述

  • isNotNull:不是null
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.isNotNull("name");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图

在这里插入图片描述

in、notIn、inSql、notInSql

  • in字段 IN (value.get(0), value.get(1), ...)
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.in("id",1,2,3,4,5);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • notIn字段 NOT IN (value.get(0), value.get(1), ...)
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notIn("id",1,2,3,4,5);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • inSql字段 IN ( sql语句 )
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.inSql("id","select id from user where age <23");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • notInSql字段 NOT IN ( sql语句 )
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notInSql("id","select id from user where age <23");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

groupBy、orderByAsc、orderByDesc、having

  • groupBy:分组 GROUP BY 字段, ...
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.groupBy("class_id");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图

在这里插入图片描述

  • orderByAsc:排序 ORDER BY 字段, ... ASC
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.orderByAsc("id");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图

在这里插入图片描述

  • orderByDesc:排序 ORDER BY 字段, ... DESC
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.orderByDesc("id");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图

在这里插入图片描述

  • havingHAVING ( sql语句 )
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.groupBy("class_id");wrapper.having("age >20");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

or、and

使用 QueryWrapperand()or() 方法可以实现多个查询条件的组合

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.isNotNull("name").and(w1 -> w1.like("name", "a").eq("age", "12")).or(w2 -> w2.eq("name", "b").ge("age", "20"));List<User> users = userMapper.selectList(wrapper);}
}

如图所示

在这里插入图片描述

exists、notExists

  • exists:拼接 EXISTS ( sql语句 )
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.exists("select * from user where id = 1");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • notExists:拼接 NOT EXISTS ( sql语句 )
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notExists("select * from user where id = 1");List<User> users2 = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

组合查询

我们可以使用多个条件来过滤数据,从而得到符合多个条件的结果。

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("id",1);wrapper.eq("name","a");wrapper.eq("age","12");List<User> users = userMapper.selectList(wrapper);}
}

如图所示

在这里插入图片描述

动态条件查询

在实际的应用中,经常会遇到根据不同条件动态构建查询条件的情况。

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){String name = null;String age = "12";QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("id",1);if(name != null) {wrapper.eq("name", name);}if(age != null) {wrapper.eq("age", age);}List<User> users = userMapper.selectList(wrapper);}
}

如图所示
在这里插入图片描述
如果你要使用XML,需要加上配置文件进行扫描

主键策略

MyBatis-Plus 中,主键策略可以通过 @TableId 注解来指定。主键生成策略有多种选择,常用的有如下几种:

  • 数据库自增主键(默认):使用数据库自增主键的方式生成主键值,对应 MySQL 的 AUTO_INCREMENT 策略或者其他数据库的类似机制。
@TableName("user")
public class User {@TableId(value = "id", type = IdType.AUTO)private Integer id;private String name;private String age;
}
  • 雪花算法生成主键:使用雪花算法生成全局唯一的主键,一般用于分布式系统中。
@TableName("user")
public class User {@TableId(value = "id", type = IdType.ASSIGN_ID)private Integer id;private String name;private String age;
}
  • UUID 生成主键:使用 UUID 来生成主键值。
@TableName("user")
public class User {@TableId(value = "id", type = IdType.ASSIGN_UUID)private Integer id;private String name;private String age;
}
  • 自定义生成策略:可以实现 IdentifierGenerator 接口自定义主键生成策略。
@TableName("user")
public class User {@TableId(value = "id", type = IdType.INPUT)private Integer id;private String name;private String age;
}

自定义生成类

@Component
public class CustomIdGenerator implements IdentifierGenerator {@Overridepublic Long nextId(Object entity) {//可以将当前传入的class全类名来作为bizKey,或者提取参数来生成bizKey进行分布式Id调用生成.String bizKey = entity.getClass().getName();//根据bizKey调用分布式ID生成long id = ....;//返回生成的id值即可.return id;}
}

注入bean,两种方法

@Bean
public IdentifierGenerator idGenerator() {return new CustomIdGenerator();
}

或者通过 MybatisPlusPropertiesCustomizer 自定义

@Bean
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {return plusProperties -> plusProperties.getGlobalConfig().setIdentifierGenerator(new CustomIdGenerator());
}

内置支持:DB2KeyGenerator、H2KeyGenerator、KingbaseKeyGenerator、OracleKeyGenerator、PostgreKeyGenerator

@Bean
public IKeyGenerator keyGenerator() {return new H2KeyGenerator();
}

逻辑删除

逻辑删除是指在数据库中并不真正删除数据记录,而是通过标记一个字段来表示数据记录的删除状态,通常是将该字段的值设置为已删除的标识。

有两种方法可以使用逻辑删除:全局配置和指定注解

  • 全局配置

在配置文件中添加全局配置

# 逻辑已删除值(默认为 1)
mybatis-plus.global-config.db-config.logic-delete-value=1
# 逻辑未删除值(默认为 0)
mybatis-plus.global-config.db-config.logic-not-delete-value=0

找到实体类字段,加上注解@TableLogic

public class User implements Serializable {private static final long serialVersionUID = 1L;private Integer id;private String name;private String age;private Integer classId;@TableLogicprivate Integer isDel;@Overridepublic String toString() {return "{id:"+id+",name:"+name+",age:"+age+"}";}
}
  • 指定注解

你可以直接使用注解进行设置

public class User implements Serializable {private static final long serialVersionUID = 1L;private Integer id;private String name;private String age;private Integer classId;@TableLogic(value = "0",delval = "1")private Integer isDel;@Overridepublic String toString() {return "{id:"+id+",name:"+name+",age:"+age+"}";}
}

如果没有配置属性值,默认情况下value = "0",delval = "1"

加上注解后对应的CRUD操作会有一些变化:

  • 插入: 不作限制
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(8);user.setName("g");user.setAge("15");userMapper.insert(user);}
}

如图所示
在这里插入图片描述

  • 查找: 追加 where 条件过滤掉已删除数据。
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = userMapper.selectById(1);}
}

如图所示
在这里插入图片描述

  • 更新: 追加 where 条件防止更新到已删除数据。
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(8);user.setName("g");user.setAge("15");userMapper.updateById(user);}
}

如图所示
在这里插入图片描述

  • 删除: 转变为 更新
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){userMapper.deleteById(8);}
}

如图所示
在这里插入图片描述

自动填充功能

自动填充功能可以用于在插入和更新操作时自动填充一些字段的值,比如创建时间、更新时间、操作人等。可以通过实现 MetaObjectHandler 接口来实现

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {LocalDateTime currentTime = LocalDateTime.now();this.strictInsertFill(metaObject, "ctime", LocalDateTime.class, currentTime);this.strictInsertFill(metaObject, "utime", LocalDateTime.class, currentTime);}@Overridepublic void updateFill(MetaObject metaObject) {LocalDateTime currentTime = LocalDateTime.now();this.strictUpdateFill(metaObject, "utime", LocalDateTime.class, currentTime);}
}

实体类加上注解@TableField(fill = FieldFill.*)

public class User implements Serializable {private static final long serialVersionUID = 1L;private Integer id;private String name;private String age;private Integer classId;private Integer isDel;@TableField(fill = FieldFill.INSERT)private LocalDateTime ctime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime utime;@Overridepublic String toString() {return "{id:"+id+",name:"+name+",age:"+age+"}";}
}

我们分别执行新增和修改操作

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(8);user.setName("g");user.setAge("15");userMapper.insert(user);}
}

如图所示

在这里插入图片描述

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(8);user.setName("g");user.setAge("15");userMapper.updateById(user);}
}

如图所示
在这里插入图片描述
可以看到执行新增和修改操作时都自动填充了相应的值。

FieldFill是一个枚举,有以下几种值:

public enum FieldFill {/*** 默认不处理*/DEFAULT,/*** 插入填充字段*/INSERT,/*** 更新填充字段*/UPDATE,/*** 插入和更新填充字段*/INSERT_UPDATE
}

防全表更新与删除插件

注入MybatisPlusInterceptor类,并配置BlockAttackInnerInterceptor拦截器

@Configuration
public class MyConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());return interceptor;}
}
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(8);user.setName("g");user.setAge("15");userMapper.update(user,null);}
}

执行结果如图所示

在这里插入图片描述

MybatisX快速开发插件

MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。

安装方法:打开 IDEA,进入 File -> Settings -> Plugins -> Browse Repositories,输入 mybatisx 搜索并安装。

在这里插入图片描述
找到Idea最右侧,数据库连接,点击新建,输入用户名密码等信息,创建Mysql连接。

在这里插入图片描述

填写完毕后,点击Apply按钮。

按下列图顺序,选择显示的数据库
在这里插入图片描述
找到对应的表
在这里插入图片描述
点击MybatisX-Generator,填写路径和包名,点击下一步
在这里插入图片描述
然后选择Myabtis-Plus 3的相关操作,按图片勾选,点击Finish

在这里插入图片描述
生成效果如下

在这里插入图片描述

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

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

相关文章

C 判断

判断结构要求程序员指定一个或多个要评估或测试的条件&#xff0c;以及条件为真时要执行的语句&#xff08;必需的&#xff09;和条件为假时要执行的语句&#xff08;可选的&#xff09;。 C 语言把任何非零和非空的值假定为 true&#xff0c;把零或 null 假定为 false。 下面…

UOS 20 安装redis 7.0.11 安装redis 7.0.11时 make命令 报错 /bin/sh: cc: command not found

UOS 20 安装redis 7.0.11 1、下载redis 7.0.112、安装redis 7.0.113、启动停止redis 7.0.114、安装过程问题记录 UOS 20 安装redis 7.0.11 安装redis 7.0.11时 make命令 报错 /bin/sh: cc: command not found、zmalloc.h:50:31: fatal error: jemalloc/jemalloc.h: No such fil…

代码随想录训练营第37天 | LeetCode 738.单调递增的数字、LeetCode 968.监控二叉树、

目录 LeetCode 738.单调递增的数字 文章讲解&#xff1a;代码随想录(programmercarl.com) 视频讲解&#xff1a;贪心算法&#xff0c;思路不难想&#xff0c;但代码不好写&#xff01;LeetCode:738.单调自增的数字_哔哩哔哩_bilibili 思路 ​​​​​​LeetCode 968.监控二…

代码随想录算法训练营第十四天| 144. 二叉树的前序遍历 ,145. 二叉树的后序遍历,94. 二叉树的中序遍历

两种写法&#xff0c;递归和非递归写法 递归&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : va…

基于协同过滤的旅游推荐系统设计与实现

基于协同过滤的旅游推荐系统设计与实现 在当今旅游业蓬勃发展的背景下&#xff0c;人们对于旅游体验的需求日益增加&#xff0c;如何为用户提供更加个性化、精准的旅游推荐成为了旅游行业的一个重要课题。为解决这一问题&#xff0c;我们设计并实现了一个基于协同过滤的旅游推…

【设计模式 03】抽象工厂模式

一个具体的工厂&#xff0c;可以专门生产单一某一种东西&#xff0c;比如说只生产手机。但是一个品牌的手机有高端机、中端机之分&#xff0c;这些具体的属于某一档次的产品都需要单独建立一个工厂类&#xff0c;但是它们之间又彼此关联&#xff0c;因为都共同属于一个品牌。我…

android开发网络通信,带你彻底搞懂Android启动速度优化

实现方案 直接依赖 这种方式实现简单&#xff0c;但是耦合太严重&#xff0c;不方便维护与开发&#xff0c;当工程逐渐增大模块逐渐增多&#xff0c;依赖关系会非常复杂&#xff0c;不推荐这种方式。 事件或广播通信 EventBus&#xff1a; 我们非常熟悉的事件总线型的通信框…

Rust学习笔记:深度解析内存管理(二)

在这个信息爆炸的时代&#xff0c;学习一门新的编程语言不仅仅是为了找到一份好工作&#xff0c;更是为了打开思维的新窗口。Rust&#xff0c;作为一门注重安全、速度和并发的系统编程语言&#xff0c;正吸引着越来越多的年轻开发者的目光。今天&#xff0c;我们将一起深入探讨…

数据结构与算法:堆排序和TOP-K问题

朋友们大家好&#xff0c;本节内容来到堆的应用&#xff1a;堆排序和topk问题 堆排序 1.堆排序的实现1.1排序 2.TOP-K问题3.向上调整建堆与向下调整建堆3.1对比两种方法的时间复杂度 我们在c语言中已经见到过几种排序&#xff0c;冒泡排序&#xff0c;快速排序&#xff08;qsor…

微信小程序云开发教程——墨刀原型工具入门(安装以及基础使用教程)

引言 作为一个小白&#xff0c;小北要怎么在短时间内快速学会微信小程序原型设计&#xff1f; “时间紧&#xff0c;任务重”&#xff0c;这意味着学习时必须把握微信小程序原型设计中的重点、难点&#xff0c;而非面面俱到。 要在短时间内理解、掌握一个工具的使用&#xf…

稀碎从零算法笔记Day4-LeetCode:交替合并字符串

前言&#xff1a;今天妹有深夜档&#xff0c;因为8点有个飞机 题型&#xff1a;字符串、双指针&#xff08;笔者没用这个思路&#xff09; 链接&#xff1a;1768. 交替合并字符串 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 著作权归作者所有。商业转…

JasperStudio中TextField文本框组件渲染之后,出现行间距不一致的问题

目录 1.1、问题描述 1.2、解决方案 1.1、问题描述 最近在处理线上遇到的一个问题,是有关JasperReports报表相关的问题,问题背景大概是这样的:我们的项目中使用了JasperReports来渲染报表,其中使用到了Text Field文本框组件,但是问题是渲染出来的数据直接会出现一些间距…

洛谷:P3068 [USACO13JAN] Party Invitations S(枚举、前缀和)

这题我们数据范围太大&#xff0c;用二维肯定是不行的&#xff0c;我们可以采用一维线性存储。 如题意&#xff0c;我们可以将每组奶牛编号都存在一维数组里面&#xff0c;只需记录每组的头尾指针就可以了。 如题中样例我们就可以存储成1 3 3 4 1 2 3 4 5 6 7 4 3 2 1 然后第…

[LeetBook]【学习日记】寻找和为指定数字的连续数字

题目 文件组合 待传输文件被切分成多个部分&#xff0c;按照原排列顺序&#xff0c;每部分文件编号均为一个 正整数&#xff08;至少含有两个文件&#xff09;。传输要求为&#xff1a;连续文件编号总和为接收方指定数字 target 的所有文件。请返回所有符合该要求的文件传输组…

【kubernetes】关于k8s集群的存储卷

目录 一、存储卷的分类 二、empty存储卷以及特点 三、hostpath存储卷以及特点 四、nfs存储卷以及特点 五、pvc存储卷 查看pv的定义 查看pvc的定义 实操&#xff1a;静态创建pv的方式 实现pvc存储卷 步骤一&#xff1a;先完成nfs的目录共享&#xff0c;需要准备不同的目…

C# 中 TryParse 将字符串转换为特定类型的方法

在 C# 中&#xff0c;TryParse 是一个用于将字符串转换为特定类型的方法。它用于尝试解析字符串并将其转换为指定类型的值&#xff0c;而不会引发异常。如果解析成功&#xff0c;它将返回 true 并将解析结果存储在输出参数中&#xff1b;如果解析失败&#xff0c;它将返回 fals…

redis10 应用问题(穿透、击穿、雪崩、分布式锁)

思维草图 缓存穿透 查询不存在的数据&#xff0c;穿透redis缓存&#xff0c;请求直接攻击后端db。 问题 当系统中引入redis缓存后&#xff0c;一个请求进来后&#xff0c;会先从redis缓存中查询&#xff0c;缓存有就直接返回&#xff08;相当于一道隔离闸&#xff0c;保护db…

vue设计原理-带你重走vue诞生路程

我们首先看下面这个小demo demo源码: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" conten…

JAVA如何利用接口实现多继承问题

hello&#xff0c;上文带大家学习了java中类的继承&#xff0c;我们可以创建一个父类&#xff0c;将类中的共性抽取出来&#xff0c;通过子类继承的方式来实现代码的复用。今天带大家学习不同类之间的另外几种关系&#xff0c;即多态抽象类和接口。 多态的概念 多态&#xff0c…

Vue 3的Composition API和vue2的不同之处

Vue 3的Composition API是Vue.js框架的一个重要更新&#xff0c;它提供了一种新的组件逻辑组织和复用方式。在Vue 2中&#xff0c;我们通常使用Options API&#xff08;data、methods、computed等&#xff09;来组织组件的逻辑&#xff0c;但这种组织方式在处理复杂组件时可能会…