Mybatis-Plus学习:快速入门、核心功能、扩展功能、插件功能

文章目录

  • MybatisPlus
    • 快速入门
      • 快速开始
      • 常见注解
      • 常见配置
    • 核心功能
      • 条件构造器(Wrapper)
      • 自定义SQL
      • Service接口
        • 基本用法
        • 基础业务接口
        • 复杂业务接口
        • Lamda查询
        • Lamda更新
        • 批量新增
    • 扩展功能
      • 代码生成
        • 代码生成器
        • 快速开发插件
      • 静态工具
      • 逻辑删除
      • 枚举处理器
      • JSON处理器
    • 插件功能
      • 分页插件
        • 通用分页实体
      • 乐观锁插件
        • 示例

MybatisPlus

快速入门

快速开始

  1. 引入依赖
<!--引入MP后,自然替代原Mybatis-->
<dependency><groupId>com.baomidou</groudId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version>
</dependency>
  1. Mapper继承
//自定义Mapper继承MP提供的BaseMapper接口
public interface UserMapper extends BaseMapper<User> {...}
  1. 实体类中添加注解声明表信息
  2. application.yml中添加配置
  3. 根据需求选择对应方法
    在这里插入图片描述

常见注解

MyBatisPlus通过扫描实体类,并基于反射获取实体类信息作为数据库表信息

  1. 约定大于配置
  • 类名驼峰转下划线作为表名(eg. UserInfo—>user_info)
  • 名为id的字段作为主键
  • 变量名驼峰转下划线作为表的字段名(eg. LocalDataTime—>local_data_time)
  1. 常用注解
  • @TableName:用于指定表名(eg. @TableName(“表名”)
  • @TableId:用于指定表中主键字段,可通过类型指定实现:
  • 自增:AUTO (eg. @TableId(“id”, type = IdType.AUTO)
  • set注入:INPUT
  • 自动分配:ASSIGN_ID,默认设置,使用雪花算法随机分配
  • @TableField:用于指定表中普通字段
  • 成员变量名与数据库字段名不一致
  • 成员变量名以is开头,但为布尔值(eg. @TableField(“is_graduate”)
  • 成员变量名与数据库关键词冲突(eg. @TableField(" ‘order’ ")
  • 成员变量名不是数据库字段(eg. @TableField(exist = false)
  1. 全部注解
    MabatisPlus注解

常见配置

在这里插入图片描述
MybatisPlus使用配置

核心功能

条件构造器(Wrapper)

  1. MP通过Wrapper支持复杂where条件,满足常用开发需求
    在这里插入图片描述
    子类AbstractWrapper
    在这里插入图片描述
    子类QueryWrapper
    在这里插入图片描述
    子类UpdateWrapper
    在这里插入图片描述
  2. 示例
/*
*查询名称带'o'的,且存款大于1000的id、username、info、balance
*select id, username, info, balance from user where username like '%o%' and balance >= 1000
*/
@Test
void testQueryWrapper() {//1.conditionQueryWrapper<User> wrapper = new QueryWrapper<User>().select("id", "username", "info", "balance").like("username", "o").ge("balance", 1000);//2.queryList<User> users = userMapper.selectList(Wrapper);user.forEach(System.out.println);
}
/*
*更新用户名为`jack`的用户的余额为2000
*update user set balance = 2000 where (username = 'jack')
*/
@Test
void testUpdateByQueryWrapper() {//1.dataUser user = new User();user.setBalance(2000);//2.conditionQueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username", "jack");//3.updateuserMapper.update(user, wrapper);
}
/*
*更新id为`1` `2` `4`的用户的余额,扣除200
*update user set balance = balance - 200 where id in (1, 2, 4)
*/
@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) ;
}
/*
*使用LamdaQueryWrapper替代第一个示例
*/
@Test
void testLamdaQueryWrapper() {//1.conditionQueryWrapper<User> wrapper = new QueryWrapper<User>().select(user::getId, User::getUsername, User::getInfo, User::getBalance).like(User::getUsername, "o").ge(User::getBalance, 1000);//2.queryList<User> users = userMapper.selectList(Wrapper);user.forEach(System.out.println);
}
  1. 用法:
  • QueryWrapperLamdaQueryWrapper构建select delete updatewhere条件部分
  • UpdateWrapperLamdaUpdateWrapper通常只在set语句使用
  • 尽量使用LamdaQueryWrapperLamdaUpdateWrapper来避免硬编码

自定义SQL

  1. 使用Wrapper构建where条件后,自定义SQL语句补充在这里插入图片描述2. 示例
/*
*基于Wrapper构建where条件
*/
List<Long> ids = List.of(1L, 2L, 4L);
int amount = 200;
//1.condition
LamdaQueryWrapper<User> wrapper = new LamdaQueryWrapper<User>..in(User::getId, ids);
//2.custom
userMapper.updateBalanceByIds(wrapper, amount);
/*
*mapper方法参数中用Param注解声明wrapper变量名,必须为ew
*/
void updateBalanceByIds(@Param("ew") LamdaQueryWrapper<User> wrapper, @Param("amount") int amount);
<!--自定义SQL,并使用Wrapper条件-->
<update id="updateBalanceByIds>UPDATE user SET balance = balance - #{amount} ${ew.customSqlSegment}
</update>

Service接口

在这里插入图片描述

基本用法

在这里插入图片描述

  1. 自定义接口继承IService接口
//指定实体类型
public interface IUserService extend IService<User> {...}
  1. 自定义实现类继承ServiceImpl实现类
@Service
//指定泛型类型和实体类型,通过反射获取对应内容
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {...}
基础业务接口
  1. 基于Restful风格实现下面接口
    在这里插入图片描述

  2. 引入依赖

<!--swagger-->
<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi2-spring-boot-starter</artifactId><version>4.1.0</version>
<dependency>
<!--web-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
<dependency>
  1. 配置swagger
knife4j:enable:trueopenapi:title:用户管理接口文档description:"用户管理接口文档"contact:jobsversion:v1.0.0group:default:group-name:defaultapi-rule:packageapi-rule-resource:- com.jobs.mp.controller
  1. 创建对应DTO、PO、VO实体
  2. 创建Controller类
@Api(tags = "用户管理接口")
@RequestMapping("/user")
@RestController
@RequiredArgsConstructor//必要参数构造方法,结合下列 final 关键字,使IUserService能够完成必要参数的构造后注入,不需要处理其中到底有多少个参数
public class UserController {private final IUserService userService;@ApiOperation("新增用户接口")@PostMappingpublic void savaUser(@RequestBody UserFormDTO userDTO) {//1.copy DTO to POUser user = BeanUtil.copyProperties(userDTO, User.class);//2.saveuserService.save(user);}@ApiOperation("删除用户接口")@DeleteMapping("{id}")public void queryUserById(@ApiParam("用户id") @PathVariable("id") Long id) {userService.removeById(id);}@ApiOperation("根据id查询用户接口")@GetMapping("{id}")public UserVo lamdaQueryUserById(@ApiParam("用户id") @PathVariable("id") Long id) {//1.getUser user = userService.getById(id);//2.copy PO to VOreturn BeanUtil.copyProperties(User, UserVO.class);}@ApiOperation("根据id批量查询用户接口")@GetMappingpublic List<User> lamdaQueryUserById(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids) {//1.getList<User> users = userService.listByIds(ids);//2.copy PO to VOreturn BeanUtil.copyToList(Users, UserVO.class);}
}
复杂业务接口

在这里插入图片描述

  1. UserMapper接口中声明方法
public interface UserMapper extends BaseMapper<User> {@Update("UPDATE user SET balance = balance - #{money} WHERE id = #{id}")void deductBalance(@Param("id") Long id, @Param("money") Integer money);
}
  1. Service接口中声明方法
public interface IUserService extends IService<User> {public void deductBalance(Long id, Integer money);
}
  1. Service实现类中定义方法
@Service
public class UserServiceImpl extends ServiceImpl implements IUserService {@Overridepublic void deductBalance(Long id, Integer money) {//1.queryUser user = getById(id);//2.check statusif (user == null || user.getStatus() == 2) {throw new RuntimeException("用户状态异常!");}//3.check balanceif (user.getBalance() < money) {throw new RuntimeException("用户余额不足!");}//4. deductbaseMapper.deductBalance(id, money);}
}
  1. Controller类中完成接口
@ApiOperation("扣减用户余额接口")
@PutMapping("/{id}/deduction/{money}")
public void deductBalance(@ApiParam("用户id") @PathVariable("id") Long id,@ApiParam("扣减金额") @PathVariable("money") Integer money) {userService.deductBalance(id, money);
}
Lamda查询

在这里插入图片描述

  1. 定义查询类
@Data
@ApiModel(description = "用户查询条件实体")
public class UserQuery {@ApiModelProperty("用户名关键字")private String name;@ApiModelProperty("用户状态:1-正常,2-冻结")private Integer status;@ApiModelProperty("余额最小值")private Integer minBalance;@ApiModelProperty("余额最大值")private Integer maxBalance;
}
  1. Service接口声明方法
public interface IUserService extends IService<User> {public void deductBalance(Long id, Integer money);List<User> queryUser(String name, Integer status, Integer minBalance, Integer maxBalance);
}
  1. Service实现类定义方法
@Service
public class UserServiceImpl extends ServiceImpl implements IUserService {@Overridepublic void deductBalance(Long id, Integer money) {...}@Overridepublic List<User> queryUser(String name, Integer status, Integer minBalance, Integer maxBalance) {return lamdaQuery().like(name != null, User::getUsername, name).eq(status != null, User::getStatus, status).ge(minBalance != null, User::getBalance, minBalance).le(maxBalance != null, User::getBalance, maxBalance).list();}
}
  1. Controller类中完成接口
@ApiOperation("根据复杂条件查询用户接口")
@GetMapping("/list")
public List<UserVO> queryUsers(UserQuery query) {//1. queryList<User> users = userService.queryUsers(query.getName(),query.getStatus(),query.getMinBalance(),query.getMaxBalance());//2. copy PO to VOreturn BeanUtil.copyToList(users, UserVO.class);
}
Lamda更新

在这里插入图片描述

  1. Service实现类中更改扣除流程
@Override
@Transactional
public void deductBalance(Long id, Integer money) {//1.queryUser user = getById(id);//2.check statusif (user == null || user.getStatus() == 2) {throw new RuntimeException("用户状态异常!");}//3.check balanceif (user.getBalance() < money) {throw new RuntimeException("用户余额不足!");}//4. deductint remainBalance = user.getBalance() - money;lamdaUpdate().set(User::getBalance, remainBalance).set(remainBalance == 0, User::getStatuse, 2).eq(User::getId, id).eq(User::getBalance, user.getBalance())//乐观锁.update();
}
批量新增

在这里插入图片描述

  1. 普通for循环逐条插入,性能极差
@Test
void testSaveOneByOne() {long startTime = System.currentTimeMillis();for (int i = 1; i <= 100000; i++) {userService.save(buildUser(i));}long endTime = System.currentTimeMillis();System.out.println(endTime - startTime;
}// 10^5 ms
  1. MP批量新增,基于预编译的批处理,性能较好
@Test
void testSaveBatch() {//1000 per time, 100 times//create listList<User> list = new ArrayList<>(1000);long startTime = System.currentTimeMillis();for (int i = 1; i <= 100000; i++) {//insert objectlist.add(buildUser(i));//each time insert onceif (i % 1000 == 0) {userService.saveBatch(list);//clearlist.clear();}}long endTime = System.currentTimeMillis();System.out.println(endTime - startTime);
}// 10^4 ms
  1. 配置jdbc参数,性能最佳
rewriteBatchedStatements = true# 10^3 ms
  1. 优化策略
  • 网络请求耗时多,减少网络请求(1—>2)
  • SQL语句多条耗时多,减少为一条(2—>3)

扩展功能

代码生成

代码生成器

引入官方依赖,在配置文档中设定生成代码
较复杂

快速开发插件
  • MyBatisX官方插件
  • MyBatisPlus插件
  1. 安装插件
  2. 连接数据库
  3. 选择要生成代码的表(可多选)
  4. 按照选填项完成设置
  5. 生成PO **Mapper I**Service **ServiceImpl **Controller等内容

静态工具

为了避免表间循环调用的情况,可使用静态Db方法代替复杂注入
在这里插入图片描述

  1. Service接口声明方法
public interface IUserService extends IService<User> {public void deductBalance(Long id, Integer money);List<User> queryUser(String name, Integer status, Integer minBalance, Integer maxBalance);List<User> queryUserAndAddressByIds(List<Long> ids);
}
  1. Service实现类中定义方法
@Override
public List<User> queryUserAndAddressByIds(List<Long> ids) {//1.user queryList<User> users = listByIds(ids);if (CollUtil.isEmpty(user)) {return Collections.emptyList();}//2.address query//2.1.get user listList<Long> userIds = users.stream().map(User::getId).collect(Collections.toList());//2.2.get address list by userIdList<Address> addresses = Db.lamdaQuery(Address.class).in(Address::getUserId, userIds).list());//2.3.transfer addressPO to VOList<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class);//2.4.grouping user`s address, one user`s address put into same collectionMap<Long, List<AddressVO> addressMap = new HashMap<>(0);if (collUtil.isNotEmpty(addressVOList)) {addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));}//3.transfer User to UserVOList<UserVO> list = new ArrayList<>(users.size());for (User user : user) {//3.1.transfer UserPO to VOUserVO vo = BeanUtil.copyProperties(user, UserVO.class);list.add(vo);//3.2.transfer addressPO to VOvo.setAddresses(addressMap.get(user.getId());}return list;
}
  1. Controller类中实现接口
@ApiOperation("根据id批量查询用户接口")
@GetMapping
public List<User> lamdaQueryUserById(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids) {return userService.queryUserAndAddressByIds(ids);
}

逻辑删除

  1. 基于代码逻辑模拟删除效果,但并不真正删除数据
eg.
UPDATE user SET deleted = 1 WHERE id = 1 AND deleted = 0
  1. 配置方式
mybatis-plus:global-config:db-config:logic-delete-field: flag # 全局逻辑删除的实体字段名,可以为boolean、integerlogic-delete-value: 1 # 逻辑已删除值(默认为1)logic-not-delete-value: 0 # 逻辑未删除值(默认为0)
  1. 问题
  • 数据库表垃圾数据增加,影响查询效率
  • SQL使用全都需要对逻辑删除字段做判断,影响查询效率
  1. 可通过数据迁移弥补逻辑删除的缺陷
  2. 失效原因及解决
  • MP依赖与代码生成器依赖版本不一致
  • 切换相同版本依赖

枚举处理器

  1. 配置
mybatis-plus:configuration:default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
  1. 状态类
@Getter
public enum UserStatus {NORMAL(1, "正常"),FROZEN(2, "冻结"),;@EnumValueprivate final int value;@JsonValue //返回时传输该注解标记的值private final String desc;UserStatus(int value, String desc) {this.value = value;this.desc = desc;}
}
  1. 使用
eg.
if (user == null || user.getStatus() == UserStatus.FROZEN) {...}

JSON处理器

eg.

#名称数据类型注释长度
5infoJSON详细信息
  1. 对应字段创建实体类
@Data
public class UserInfo {private Integer age;private String intro;private String gender;
}
  1. 字段标注注解,并指定类型处理器
...
@TableField(typeHandler = JacksonTypeHandler.class)
private UserInfo info;
...
  1. 向表类添加注解,开启映射
@Data
@TableName(value="user", autoResultMap=true)
public class User {...}

插件功能

拦截器描述
TenantLineInnerInterceptor多租户插件
DynamicTableNameInnerInterceptor动态表名插件
PaginationInnerInterceptor分页插件
OptimisitcLockerInnerInterceptor乐观锁插件
IllegalSQLInnerInterceptorSQL性能规范插件(检测并拦截垃圾SQL)
BlockAttackInnerInterceptor防止全表更新和删除的插件

分页插件

  1. 配置类中注册MP核心插件,添加分页插件
@Configuration
public class MybatisConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {//初始化核心插件MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();//添加分页插件PaginationInnerInterceptor pageInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);pageInterceptor.setMaxLimit(1000L);//设置分页上限interceptor.addInnerInterceptor(pageInterceptor);return interceptor;}
}
  1. ServiceTest类中使用分页插件
@Test
void testPageQuery() {int pageNo = 1, pageSize = 2;//1.prepare pagination//1.1.page conditionPage<User> page = Page.of(pageNo, pageSize);//1.2.sort conditionpage.addOrder(new OrderItem("balance", true));page.addOrder(new OrderItem("id", true));//2.pagination queryPage<User> p = userService.page(page);//3.analysislong total = p.getTotal();System.out.println("total = " + total);long pages = p.getPages();System.out.println("pages = " + pages);List<User> users = p.getRecords();users.forEach(System.out::println);
}
通用分页实体

在这里插入图片描述
在这里插入图片描述

  1. 分页查询实体UserQuery.java
@EqualsAndHashCode(callSuper = true)
@Data
@ApiModel(description="用户查询条件实体")
public cl ass UserQuery extends PageQuery {@ApiModelProperties("用户名关键字")private String name;@ApiModelProperties("用户状态:1-正常,2-冻结")private Integer status;@ApiModelProperties("余额最小值")private Integer minBalance;@ApiModelProperties("余额最大值")private Integer maxBalance;
}
  1. PageDTO.java
@Data
@ApiModel(description="分页结果")
public class PageDTO<T> {@ApiModelProperties("总条数")private Integer total;@ApiModelProperties("总页数")private Integer pages;@ApiModelProperties("集合")private Integer list;
}
  1. Service接口声明
...
PageDTO<UserVO> queryUsersPage(UserQuery query);
...
  1. Service实现类定义
@Override
public PageDTO<UserVO> queryUsersPage(UserQuery query) {String name = query.getName();Integer status = query.getStatus();//1.condition//1.1.page conditionPage<User> page = Page.of(query.getPageNo(), query.getPageSize());//1.2.sort conditionif (StrUtil.isNotBlank(query.getSortBy())) {//not nullpage.addOrder(new OrderItem(query.getSortBy(), query.getIsAsc()));}else {//null, sory by update timepage.addOrder(new OrderItem("update_time", false));}//2.pagination queryPage<User> p = lamdaQuery().like(name != null, User::getUsername, name).eq(status != null, User::getStatus, status).page(page);//3.pack VOPageDTO<UserVO> dto = new PageDTO<>();//3.1.total recordsdto.setTotal(p.getTotal());//3.2.total pagesdto.setPages(p.getPages());//3.3.current pageList<User> records = p.getRecords();if (CollUtil.isEmpty(records)) {dto.setList(Collections.emptyList());return dto;}//3.4.copy user`s VOdto.setList(BeanUtil.copyToList(records, UserVO.class));//4.returnreturn dto
}
  1. Controller类中实现
@ApiOperation("根据条件分页查询用户接口")
@GetMapping("/List")
public PageDTO<UserVO> queryUsersPage(UserQuery query) {return userService.queryUsersPage(query);
}

乐观锁插件

  1. 定义
  • 乐观锁:认为操作数据时始终处于乐观状态,不会有他人同时修改数据。因此乐观锁不会上锁,只在执行更新时判断他人是否在此期间修改过该数据,若修改则放弃本次操作,否则执行;
  • 悲观锁:认为操作始终处于悲观状态,存在他人同时修改数据。因此悲观锁操作时直接锁定数据,操作结束后才会释放,期间他人无法修改该数据
  1. 实现方式
  • 取出记录时,获取当前version
  • 更新时附带此version
  • 执行更新时,判定SET version = newVersion WHERE version = oldVersion
  • 如果version不对,则更新失败
示例
  1. 表实体中加上version
@Data
@TableNmae("user")
public class User {...//数据库表中也应有此字段@Version@TableField(value = "version")private Integer version;
}
  1. 启动类加上注解@MapperScan(basePackages = "com.kaven.mybatisplus.dao")
  2. 添加插件
@Configuration
public class MybatisConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {//初始化核心插件MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();//添加分页插件PaginationInnerInterceptor pageInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);pageInterceptor.setMaxLimit(1000L);//设置分页上限interceptor.addInnerInterceptor(pageInterceptor);//添加乐观锁插件interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}
  1. 测试
@SpringBootTest
public class LockerTest {@Autowiredprivate UserMapper userMapper;@Testpublic void updateById() {User user = userMapper.selectById("1");int version = user.getVersion();user.setPassword("new password");user.setVersion(version);int rows = userMapper.updateById(user);System.out.println("infect: " + rows);}
}
  1. 说明
  • 支持的数据类型有:int Integer long Long Date Timestamp LocalDateTime
  • 整数类型下newVersion = oldVersion + 1
  • newVersion会写回到entity
  • 仅支持updateById(entity)update(entity, wrapper)方法
  • update(entity, wrapper)方法下,wrapper无法复用

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

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

相关文章

万界星空科技商业开源MES+项目合作+商业开源低代码平台

今天我想和大家分享的是一套商业开源的 MES制造执行管理系统带源码。对于制造业而言&#xff0c;MES 是一个至关重要的系统&#xff0c;它可以帮助企业提高生产效率、优化资源利用、提高产品质量&#xff0c;从而增强市场竞争力。 什么是 MES&#xff1f; MES 是指通过计算机技…

# notepad++ 编辑器英文版,如何打开自动换行

notepad 编辑器英文版&#xff0c;如何打开自动换行 在Notepad中&#xff0c;如果你想要开启自动换行功能&#xff0c;可以按照以下步骤操作&#xff1a; 1、打开 Notepad 编辑器。 1.1. 依次点击菜单栏中的【视图】&#xff0c;英文版对应【View】。1.2. 在【视图】下拉菜单…

商务谈判技巧与口才书籍有哪些类型

商务谈判技巧与口才书籍有哪些类型&#xff08;3篇&#xff09; 商务谈判技巧与口才书籍的类型丰富多样&#xff0c;以下从三个角度进行介绍&#xff1a; **篇&#xff1a;基础理论与策略类书籍 这类书籍通常深入剖析谈判的本质&#xff0c;系统介绍谈判的原理、技巧和策略。…

量子城域网建设设备系列(二):量子密钥管系统(KMS)

在上文介绍光量子交换机的文章中我们提到&#xff0c;量子保密通信网络的通道切换是由量子密钥管理系统&#xff08;Key Management System&#xff0c;KMS&#xff09;给光量子交换机下发信道切换指令&#xff0c;实现整个网络中任意两对量子密钥分发终端的量子信道互联互通&a…

【跟马少平老师学AI】-【神经网络是怎么实现的】(九)长短期记忆网络

一句话归纳&#xff1a; 1&#xff09;RNN也会存在梯度消失的问题。 2&#xff09;同一句话&#xff0c;对于不同的任务&#xff0c;句中不同的词起的作用也不一样。 3&#xff09;LSTM&#xff08;长短期记忆&#xff09;子网络&#xff1a; 门&#xff0c;让输入经过运算&…

与Apollo共创生态:探索自动驾驶的未来蓝图

目录 引言Apollo开放平台Apollo开放平台企业生态计划Apollo X 企业自动驾驶解决方案&#xff1a;加速企业场景应用落地Apollo开放平台携手伙伴共创生态生态共创会员权益 个人心得与展望技术的多元化应用数据驱动的智能化安全与可靠性的重视 结语 引言 就在2024年4月19日&#x…

SpringBoot的ProblemDetails

1.RFC 7807 之前的项目如果出现异常&#xff0c;默认跳转到error页面。或者是抛出500 异常。 但是对于前后端分离的项目&#xff0c;Java程序员不负责页面跳转&#xff0c;只需要 把错误信息交给前端程序员处理即可。而RFC 7807规范就是将异常 信息转为JSON格式的数据。这个…

导数之光:探寻机器学习中的微变奥秘

在当今这个数据驱动的时代&#xff0c;机器学习以其强大的学习和预测能力&#xff0c;成为了推动科技进步的重要力量。而在机器学习的背后&#xff0c;数学原理&#xff0c;尤其是导数的应用&#xff0c;为其提供了坚实的理论支撑。本文将详细探讨导数在机器学习中的体现&#…

如何使用 GPT API 从 PDF 出版物导出研究图表?

原文地址&#xff1a;how-to-use-gpt-api-to-export-a-research-graph-from-pdf-publications 揭示内部结构——提取研究实体和关系 2024 年 2 月 6 日 介绍 研究图是研究对象的结构化表示&#xff0c;它捕获有关实体的信息以及研究人员、组织、出版物、资助和研究数据之间的关…

IDEA 创建Servlet-HelloWorldServlet

servlet 1.创建空项目2.配置web项目3.配置Tomcat4.加载Tomcat包5.创建HelloWorldServlet类6.配置web.xml7.运行get与post请求 1.创建空项目 2.配置web项目 3.配置Tomcat 4.加载Tomcat包 5.创建HelloWorldServlet类 public class controller extends HttpServlet {Override//get…

【Mellanox命令之】如何查看系统MFT版本是否与OFED和FW匹配?(mst version、rpm -qa|grep mft)

0. 背景 如果出现升级了OFED&#xff0c;以及FW、lib等&#xff0c;但是在Debug中遇到异常。可能与mft版本不匹配有关。 那么如何获取mft与OFED、FW之间的匹配关系呢&#xff1f; 1. 查看MFT版本 mft因为不是一个命令&#xff0c;而是4类工具的集合&#xff08;参考兄弟篇&a…

DRF版本组件源码分析

DRF版本组件源码分析 在restful规范中要去&#xff0c;后端的API中需要体现版本。 3.6.1 GET参数传递版本 from rest_framework.versioning import QueryParameterVersioning单视图应用 多视图应用 # settings.pyREST_FRAMEWORK {"VERSION_PARAM": "versi…

图像处理1,灰度,data,for循环批处理图片,图片属性查看,图片单通道查看,椒盐噪声的生成,滤波处理,图像分割

图像处理1 灰度处理data库的使用for循环批处理图像对图像属性的查看图片类型图片尺寸图片宽度图像高度通道数总像素个数最大像素值最小像素值&#xff0c;像素平均值图像点像素值 for循环分别显示图像rgb通道椒盐噪声的生成中值滤波处理高斯模糊处理图像切割 灰度处理 from sk…

SpringCloudAlibaba:3.1dubbo

dubbo 概述 简介 Apache Dubbo 是一款 RPC 服务开发框架&#xff0c;用于解决微服务架构下的服务治理与通信问题 官方提供了 Java、Golang、Rust 等多语言 SDK 实现 Dubbo的开源故事 最早在2008年&#xff0c;阿里巴巴就将Dubbo捐献到开源社区&#xff0c;它很快成为了国内开源…

面试:Mybatis(MyBatis执行流程、延迟加载、MyBatis的缓存)

目录 一、MyBatis执行流程 二、MyBatis是否支持延迟加载&#xff1f; 1、什么是延迟加载&#xff1f; 2、延迟加载的原理 三、MyBatis的缓存 1、一级缓存 2、二级缓存 3、注意事项 一、MyBatis执行流程 读取MyBatis配置文件: mybatis-config.xml加载运行环境和映射文件构…

自定义表单元素组件内容变化触发ElForm重新校验

对于下图中“付费类型”怎么实现有很多种方式&#xff0c;我能想到的是以下两种&#xff1a; Element Plus的RadioButton自定义组件 1. RadioButton 它本质上就是一个单选组件&#xff0c;它跟Element Plus的RadioButton本质上没有区别&#xff0c;无非是外观上的差别。那么…

Vue阶段练习:组件拆分

页面开发思路 分析页面&#xff0c;按模块拆分组件&#xff0c;搭架子&#xff08;局部或全局注册&#xff09;根据设计图&#xff0c;编写html结构css样式拆分封装通用小组件&#xff08;局部或全局注册&#xff09;将来通过js动态渲染实现功能 BaseBrandItem.vue <templ…

数字旅游以科技创新为动力:推动旅游服务的智能化、网络化和个性化发展,满足游客日益增长的多元化、个性化需求

目录 一、引言 二、科技创新推动旅游服务智能化发展 1、智能化技术的引入与应用 2、智能化提升旅游服务效率与质量 三、科技创新推动旅游服务网络化发展 1、网络化平台的构建与运营 2、网络化拓宽旅游服务渠道与范围 四、科技创新推动旅游服务个性化发展 1、个性化需求…

Flutter笔记:谈Material状态属性-为什么FlatButton等旧版按钮就废弃了

Flutter笔记 谈Material状态属性-为什么FlatButton等旧版按钮就废弃了 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this artic…

C#知识|Dictionary泛型集合的使用总结

哈喽,你好,我是雷工! 以下是C#Dictionary泛型集合的学习笔记。 01 Dictionary泛型集合 1.1、Dictionary<K,V>通常称为字典, 1.2、其中<K,V>是自定义的,用来约束集合中元素类型。 1.3、在编译时检查类型约束, 1.4、无需装箱拆箱操作, 1.5、操作与哈希表(Ha…