MybatisPlus多表连接查询

2023-11-02

一、序言

(一)背景内容

软件应用技术架构中DAO层最常见的选型组件为MyBatis,熟悉MyBatis的朋友都清楚,曾几何时MyBatis是多么的风光,使用XML文件解决了复杂的数据库访问的难题。时至今日,曾经的屠龙者终成恶龙,以XML文件为基础的数据库访问技术变得臃肿、复杂,维护难度直线上升。

MybatisPlus对常见的数据库访问进行了封装,访问数据库大大减少了XML文件的依赖,开发者从臃肿的XML文件中获得了较大限度的解脱。

MybatisPlus官方并没有提供多表 连接查询 的通用解决方案,然而连接查询是相当普遍的需求。解决连接查询有两种需求,一种是继续使用MyBatis提供XML文件解决方式;另一种本文提供的解决方案。

事实上笔者强烈推荐彻底告别通过XML访问数据库,并不断探索新式更加友好、更加自然的解决方式,现分享最新的MybatisPlus技术的研究成果。

(二)场景说明

为了说明连接查询的关系,这里以学生、课程及其关系为示例。

(三)前期准备

此部分需要读者掌握以下内容:Lambda 表达式、特别是方法引用;函数式接口;流式运算等等,否则理解起来会有些吃力。

实体类与 Vo 的映射关系,作者创造性的引入特别构造器,合理利用继承关系,极大的方便了开发者完成实体类向 Vo 的转换。

空指针异常忽略不处理,借助 Optional 类实现,详情移步 Java8 新特性 查看。

二、一对一查询

一对一查询最典型的应用场景是将 id 替换成 name ,比如将 userId 替换成 userName 。

(一)查询单条记录

查询单条记录是指返回值仅有一条记录,通常是以唯一索引作为条件的返回查询结果。

1、示例代码

/**
 * 查询单个学生信息(一个学生对应一个部门)
 */
public UserVo getOneUser(Integer userId) {
    LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery(User.class)
        .eq(User::getUserId, userId);
    // 先查询用户信息
    User user = userMapper.selectOne(wrapper);
    // 转化为Vo
    UserVo userVo = Optional.ofNullable(user).map(UserVo::new).orElse(null);
    // 从其它表查询信息再封装到Vo
    Optional.ofNullable(userVo).ifPresent(this::addDetpNameInfo);
    return userVo;
}

附属表信息补充

/**
 * 补充部门名称信息
 */
private void addDetpNameInfo(UserVo userVo) {
    LambdaQueryWrapper<Dept> wrapper = Wrappers.lambdaQuery(Dept.class)
        .eq(Dept::getDeptId, userVo.getDeptId());
    Dept dept = deptMapper.selectOne(wrapper);
    Optional.ofNullable(dept).ifPresent(e -> userVo.setDeptName(e.getDeptName()));
}

2、理论分析

查询单个实体共分为两个步骤:根据条件查询主表数据(需处理空指针异常);封装 Vo 并查询附属表数据。

查询结果(VO)只有一条记录,需要查询两次数据库,时间复杂度为 O(1) 。

(二)查询多条记录

查询多条记录是指查询结果为列表,通常是指以普通索引为条件的查询结果。

1、示例代码

/**
 * 批量查询学生信息(一个学生对应一个部门)
 */
public List<UserVo> getUserByList() {
    // 先查询用户信息(表现形式为列表)
    List<User> user = userMapper.selectList(Wrappers.emptyWrapper());
    List<UserVo> userVos = user.stream().map(UserVo::new).collect(toList());
    // 此步骤可以有多个
    addDeptNameInfo(userVos);
    return userVos;
}

附属信息补充

private void addDeptNameInfo(List<UserVo> userVos) {
    // 提取用户userId,方便批量查询
    Set<Integer> deptIds = userVos.stream().map(User::getDeptId).collect(toSet());
    // 根据deptId查询deptName(查询前,先做非空判断)
    List<Dept> dept = deptMapper.selectList(Wrappers.lambdaQuery(Dept.class).in(Dept::getDeptId, deptIds));
    // 构造映射关系,方便匹配deptId与deptName
    Map<Integer, String> hashMap = dept.stream().collect(toMap(Dept::getDeptId, Dept::getDeptName));
    // 封装Vo,并添加到集合中(关键内容)
    userVos.forEach(e -> e.setDeptName(hashMap.get(e.getDeptId())));
}

2、理论分析

先查询包含 id 的列表记录,从结果集中析出 id 并转化成批查询语句再访问数据库,从第二次调用结果集中解析出 name 。

查询结果(VO)有多条记录,但仅调用两次数据库,时间复杂度为 O(1) 。

(三)查询多条记录(分页)

分页查询实体的思路与查询列表的思路相似,额外多处一步分页泛型转换。

1、示例代码

/**
 * 分页查询学生信息(一个学生对应一个部门)
 */
public IPage<UserVo> getUserByPage(Page<User> page) {
    // 先查询用户信息
    IPage<User> xUserPage = userMapper.selectPage(page, Wrappers.emptyWrapper());
    // 初始化Vo
    IPage<UserVo> userVoPage = xUserPage.convert(UserVo::new);
    if (userVoPage.getRecords().size() > 0) {
        addDeptNameInfo(userVoPage);
    }
    return userVoPage;
}

查询补充信息

private void addDeptNameInfo(IPage<UserVo> userVoPage) {
    // 提取用户userId,方便批量查询
    Set<Integer> deptIds = userVoPage.getRecords().stream().map(User::getDeptId).collect(toSet());
    // 根据deptId查询deptName
    List<Dept> dept = deptMapper.selectList(Wrappers.lambdaQuery(Dept.class).in(Dept::getDeptId, deptIds));
    // 构造映射关系,方便匹配deptId与deptName
    Map<Integer, String> hashMap = dept.stream().collect(toMap(Dept::getDeptId, Dept::getDeptName));
    // 将查询补充的信息添加到Vo中
    userVoPage.convert(e -> e.setDeptName(hashMap.get(e.getDeptId())));
}

IPage 接口中 convert 方法,能够实现在原实例上修改。

2、理论分析

先查询包含 id 的列表记录,从结果集中析出 id 并转化成批查询语句再访问数据库,从第二次调用结果集中解析出 name 。

查询结果(VO)有多条记录,但仅调用两次数据库,时间复杂度为 O(1) 。

三、一对多查询

一对多查询最常见的场景是查询部门所包含的学生信息,由于一个部门对应多个学生,每个学生对应一个部门,因此称为一对多查询。

(一)查询单条记录

1、示例代码

/**
 * 查询单个部门(其中一个部门有多个用户)
 */
public DeptVo getOneDept(Integer deptId) {
    // 查询部门基础信息
    LambdaQueryWrapper<Dept> wrapper = Wrappers.lambdaQuery(Dept.class).eq(Dept::getDeptId, deptId);
    DeptVo deptVo = Optional.ofNullable(deptMapper.selectOne(wrapper)).map(DeptVo::new).orElse(null);
    Optional.ofNullable(deptVo).ifPresent(this::addUserInfo);
    return deptVo;
}

补充附加信息

private void addUserInfo(DeptVo deptVo) {
    // 根据部门deptId查询学生列表
    LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery(User.class).eq(User::getDeptId, deptVo.getDeptId());
    List<User> users = userMapper.selectList(wrapper);
    deptVo.setUsers(users);
}

2、理论分析

整个过程共分为两个阶段:通过部门表中主键查询指定部门信息,通过学生表中部门ID外键查询学生信息,将结果合并,形成返回值(Vo)。

一对多查询单条记录整个过程至多需要调用2次数据库查询,查询次数为常数,查询时间复杂度为 O(1) 。

(二)查询多条记录

1、示例代码

/**
 * 查询多个部门(其中一个部门有多个用户)
 */
public List<DeptVo> getDeptByList() {
    // 按条件查询部门信息
    List<Dept> deptList = deptMapper.selectList(Wrappers.emptyWrapper());
    List<DeptVo> deptVos = deptList.stream().map(DeptVo::new).collect(toList());
    if (deptVos.size() > 0) {
        addUserInfo(deptVos);
    }
    return deptVos;
}

补充附加信息

private void addUserInfo(List<DeptVo> deptVos) {
    // 准备deptId方便批量查询用户信息
    Set<Integer> deptIds = deptVos.stream().map(Dept::getDeptId).collect(toSet());
    // 用批量deptId查询用户信息
    List<User> users = userMapper.selectList(Wrappers.lambdaQuery(User.class).in(User::getDeptId, deptIds));
    // 重点:将用户按照deptId分组
    Map<Integer, List<User>> hashMap = users.stream().collect(groupingBy(User::getDeptId));
    // 合并结果,构造Vo,添加集合列表
    deptVos.forEach(e -> e.setUsers(hashMap.get(e.getDeptId())));
}

2、理论分析

整个过程共分为三个阶段:通过普通索引从部门表中查询若干条记录;将部门ID转化为批查询从学生表中查询学生记录;将学生记录以部门ID为单位进行分组,合并结果,转化为Vo。

一对多查询多条记录需要调用2次数据库查询,查询次数为常数,查询时间复杂度为 O(1) 。

(三)查询多条记录(分页)

1、示例代码

/**
 * 分页查询部门信息(其中一个部门有多个用户)
 */
public IPage<DeptVo> getDeptByPage(Page<Dept> page) {
    // 按条件查询部门信息
    IPage<Dept> xDeptPage = deptMapper.selectPage(page, Wrappers.emptyWrapper());
    IPage<DeptVo> deptVoPage = xDeptPage.convert(DeptVo::new);
    if (deptVoPage.getRecords().size() > 0) {
        addUserInfo(deptVoPage);
    }
    return deptVoPage;
}

查询补充信息

private void addUserInfo(IPage<DeptVo> deptVoPage) {
    // 准备deptId方便批量查询用户信息
    Set<Integer> deptIds = deptVoPage.getRecords().stream().map(Dept::getDeptId).collect(toSet());
    LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery(User.class).in(User::getDeptId, deptIds);
    // 用批量deptId查询用户信息
    List<User> users = userMapper.selectList(wrapper);
    // 重点:将用户按照deptId分组
    Map<Integer, List<User>> hashMap = users.stream().collect(groupingBy(User::getDeptId));
    // 合并结果,构造Vo,添加集合列表
    deptVoPage.convert(e -> e.setUsers(hashMap.get(e.getDeptId())));
}

2、理论分析

整个过程共分为三个阶段:通过普通索引从部门表中查询若干条记录;将部门ID转化为批查询从学生表中查询学生记录;将学生记录以部门ID为单位进行分组,合并结果,转化为Vo。

一对多查询多条记录需要调用2次数据库查询,查询次数为常数,查询时间复杂度为 O(1) 。

四、多对多查询

MybatisPlus 实现多对多查询是一件极富挑战性的任务,也是连接查询中最困难的部分。

以空间置换时间,借助于流式运算,解决多对多查询难题。

多对多查询相对于一对多查询,增加了流式分组运算、批量 HashMap 取值等内容。

(一)查询单条记录

查询单条记录一般是指通过两个查询条件查询出一条匹配表中的记录。

1、示例代码

public StudentVo getStudent(Integer stuId) {
    // 通过主键查询学生信息
    StudentVo studentVo = ConvertUtils.convertObj(getById(stuId), StudentVo::new);
    LambdaQueryWrapper<StuSubRelation> wrapper = Wrappers.lambdaQuery(StuSubRelation.class).eq(StuSubRelation::getStuId, stuId);
    // 查询匹配关系
    List<StuSubRelation> stuSubRelations = stuSubRelationMapper.selectList(wrapper);
    Set<Integer> subIds = stuSubRelations.stream().map(StuSubRelation::getSubId).collect(toSet());
    if (studentVo != null && subIds.size() > 0) {
        List<Subject> subList = subjectMapper.selectList(Wrappers.lambdaQuery(Subject.class).in(Subject::getId, subIds));
        List<SubjectBo> subBoList = ConvertUtils.convertList(subList, SubjectBo::new);
        HashBasedTable<Integer, Integer, Integer> table = getHashBasedTable(stuSubRelations);
        subBoList.forEach(e -> e.setScore(table.get(stuId, e.getId())));
        studentVo.setSubList(subBoList);
    }
    return studentVo;
}

2、理论分析

多对多单条记录查询最多访问数据库3次,先查询学生信息,然后查询学生与课程匹配信息,最后查询课程分数信息,查询时间复杂度为 O(1) 。

(二)查询多条记录

1、示例代码

public List<StudentVo> getStudentList() {
    // 通过主键查询学生信息
    List<StudentVo> studentVoList = ConvertUtils.convertList(list(), StudentVo::new);
    // 批量查询学生ID
    Set<Integer> stuIds = studentVoList.stream().map(Student::getId).collect(toSet());
    LambdaQueryWrapper<StuSubRelation> wrapper = Wrappers.lambdaQuery(StuSubRelation.class).in(StuSubRelation::getStuId, stuIds);
    List<StuSubRelation> stuSubRelations = stuSubRelationMapper.selectList(wrapper);
    // 批量查询课程ID
    Set<Integer> subIds = stuSubRelations.stream().map(StuSubRelation::getSubId).collect(toSet());
    if (stuIds.size() > 0 && subIds.size() > 0) {
        HashBasedTable<Integer, Integer, Integer> table = getHashBasedTable(stuSubRelations);
        List<Subject> subList = subjectMapper.selectList(Wrappers.lambdaQuery(Subject.class).in(Subject::getId, subIds));
        List<SubjectBo> subjectBoList = ConvertUtils.convertList(subList, SubjectBo::new);
        Map<Integer, List<Integer>> map = stuSubRelations.stream().collect(groupingBy(StuSubRelation::getStuId, mapping(StuSubRelation::getSubId, toList())));
        for (StudentVo studentVo : studentVoList) {
            // 获取课程列表
            List<SubjectBo> list = ListUtils.select(subjectBoList, e -> emptyIfNull(map.get(studentVo.getId())).contains(e.getId()));
            // 填充分数
            list.forEach(e -> e.setScore(table.get(studentVo.getId(), e.getId())));
            studentVo.setSubList(list);
        }
    }
    return studentVoList;
}

2、理论分析

多对多N条记录查询由于使用了批查询,因此最多访问数据库也是3次,先查询学生信息,然后查询学生与课程匹配信息,最后查询课程分数信息,查询时间复杂度为 O(1) 。

(三)查询多条记录(分页)

1、示例代码

public IPage<StudentVo> getStudentPage(IPage<Student> page) {
    // 通过主键查询学生信息
    IPage<StudentVo> studentVoPage = ConvertUtils.convertPage(page(page), StudentVo::new);
    // 批量查询学生ID
    Set<Integer> stuIds = studentVoPage.getRecords().stream().map(Student::getId).collect(toSet());
    LambdaQueryWrapper<StuSubRelation> wrapper = Wrappers.lambdaQuery(StuSubRelation.class).in(StuSubRelation::getStuId, stuIds);
    // 通过学生ID查询课程分数
    List<StuSubRelation> stuSubRelations = stuSubRelationMapper.selectList(wrapper);
    // 批量查询课程ID
    Set<Integer> subIds = stuSubRelations.stream().map(StuSubRelation::getSubId).collect(toSet());
    if (stuIds.size() > 0 && subIds.size() > 0) {
        HashBasedTable<Integer, Integer, Integer> table = getHashBasedTable(stuSubRelations);
        // 学生ID查询课程ID组
        Map<Integer, List<Integer>> map = stuSubRelations.stream().collect(groupingBy(StuSubRelation::getStuId, mapping(StuSubRelation::getSubId, toList())));

        List<Subject> subList = subjectMapper.selectList(Wrappers.lambdaQuery(Subject.class).in(Subject::getId, subIds));
        List<SubjectBo> subBoList = ConvertUtils.convertList(subList, SubjectBo::new);
        for (StudentVo studentVo : studentVoPage.getRecords()) {
            List<SubjectBo> list = ListUtils.select(subBoList, e -> emptyIfNull(map.get(studentVo.getId())).contains(e.getId()));
            list.forEach(e -> e.setScore(table.get(studentVo.getId(), e.getId())));
            studentVo.setSubList(list);
        }
    }
    return studentVoPage;
}

2、理论分析

多对多N条记录分页查询由于使用了批查询,因此最多访问数据库也是3次,先查询学生信息,然后查询学生与课程匹配信息,最后查询课程分数信息,查询时间复杂度为 O(1) 。

五、总结与拓展

(一)总结

通过上述分析,能够用 MybatisPlus 解决多表连接查询中的 一对一 、 一对多 、 多对多 查询。

o(1)

(二)拓展

MybatisPlus能很好的解决单表查询问题,同时借助在单表查询的封装能很好地解决连接查询问题。

本方案不仅解决了连接查询问题,同时具备如下内容拓展:

  • 当数据量较大时,仍然具有稳定的查询效率

当数据量达到百万级别时,传统的单表通过索引查询已经面临挑战,普通的多表连接查询性能随着数据量的递增呈现指数级下降。

本方案通过将连接查询转化为主键(索引)查询,查询性能等效于单表查询。

  • 与二级缓存配合使用进一步提高查询效率

当所有的查询均转化为以单表为基础的查询后,方能安全的引入二级缓存。二级缓存的单表增删改查操作自适应联动,解决了二级缓存的脏数据问题。

原文地址:  https://blog.51cto.com/u_15495434/4955709

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MybatisPlus多表连接查询 的相关文章

  • HTTP 状态 404 - 请求的资源不可用

    在使用 MyEclipse IDE 中的 Tomcat 服务器和 Struts 2 框架时 我遇到了反复出现的问题 我将我的程序作为服务器应用程序运行 当它运行时 默认的index jsp 文件将成功打开 但应用程序的其他过去都不起作用 当
  • java中的csv到pdf文件

    我正在尝试获得一个csv文件解析为pdf 到目前为止我所拥有的内容附在下面 我的问题是这段代码最终出现在 pdf 中的文件在 csv 文件的第一行被截断 我不明白为什么 附示例 本质上我想要一个没有任何操作的 csv 文件的 pdf 版本
  • 用 @DataJpaTest 注释的测试不是用 @Autowired 注释的自动装配字段

    我有一个 Spring Boot 应用程序 其中包含 Spring Data Jpa 存储库 我需要围绕这个存储库运行单元 或组件 测试 我对 Spring Data Jpa 没有太多经验 这是我的测试 这很简单 我无法让它通过 impor
  • MP3:一种以毫秒为单位获取任何给定字节位置的位置的方法?

    我创建了一个 servlet 它返回从客户端请求的任何给定字节位置开始的流 来自 MP3 文件 这允许客户端在任何给定字节位置立即开始播放 而无需进行任何本地查找 现在 我有一个滑块可以直观地显示进度 我正在使用当前字节位置来更新滑块 但是
  • java.lang.Class: 在 java 程序中初始化 log4j 属性文件时出错

    我正在尝试使用 log4j 运行独立的 java 程序 但在调试时收到以下消息 控制台上没有 log4j 相关日志 log Logger 1343 java lang Class ERROR in 18b4aac2 有人可以建议这里出了什么
  • Java 创建浮雕(红/蓝图像)

    我正在编写一个 Java 游戏引擎 http victoryengine org http victoryengine org 并且我一直在尝试生成具有深度的 3D 图像 您可以使用那些红色 蓝色眼镜看到 我正在使用 Java2D 进行图形
  • 如何从另一个xml文件动态更新xml文件?

    我想从另一个 xml 文件更新 xml 文件 我使用了一个 xml 文件 如下所示 one xml
  • 无法加载 jar 文件的主类

    我使用 Eclipse IDE 开发了一个应用程序 创建应用程序后 我以 jar 格式导出项目 当我尝试运行此 jar 文件时 出现错误 无法加载主类 请帮忙 当您将项目导出为 jar 时 请参阅此所以问题 https stackoverf
  • 方法断点可能会大大减慢调试速度

    每当向方法声明行添加断点 在 Intellij IDEA 或 Android Studio 中 时 都会出现一个弹出窗口 方法断点可能会大大减慢调试速度 为什么会这样戏剧性地减慢调试速度 是我的问题吗 将断点放在函数的第一行有什么不同 Th
  • Java 变量的作用域

    我不明白为什么这段代码的输出是10 package uno public class A int x 10 A int x 12 new B public static void main String args int x 11 new
  • 场景生成器删除 fxml 文件中的导入

    我使用场景构建器 Gluon Scene Builder JavaFX Scene Builder 8 1 1 来创建应用程序的 UI 并使用 Eclipse 开发 JavaFX 现在 每次我在场景生成器中保存某些内容时 它都会从 fxml
  • 如何将 XMP XML 块序列化为现有的 JPEG 图像?

    我有许多 JPEG 图像 其中包含损坏的 XMP XML 块 我可以轻松修复这些块 但我不确定如何将 固定 数据写回图像文件 我目前正在使用 JAVA 但我愿意接受任何能让这项任务变得容易的事情 这是目标关于 XMP XML 的另一个问题
  • 参数动态时如何构建 JPQL 查询?

    我想知道是否有一个好的解决方案来构建基于过滤器的 JPQL 查询 我的查询太 富有表现力 我无法使用 Criteria 就像是 query Select from Ent if parameter null query WHERE fiel
  • tomcat 过滤所有 web 应用程序

    问题 我想对所有网络应用程序进行过滤 我创建了一个过滤器来监视对 apache tomcat 服务器的请求 举例来说 它称为 MyFilter 我在 netbeans 中创建了它 它创建了 2 个独立的目录 webpages contain
  • 如何为 Jackson 编写一个包罗万象的(反)序列化器

    当您提前知道类型时 编写自定义序列化器非常容易 例如 MyType一个人可以写一个MyTypeSerializer extends StdSerializer
  • ExceptionHandler 不适用于 Throwable

    我们的应用程序是基于 Spring MVC 的 REST 应用程序 我正在尝试使用 ExceptionHandler 注释来处理所有错误和异常 I have ExceptionHandler Throwable class public R
  • 阻止 OSX 变音符号为所有用户禁用 Java 中的 KeyBindings?

    注 我知道这个问题 https stackoverflow com questions 40335285 java keybinds stop working after holding down a key用户必须输入终端命令才能解决此问
  • struts 教程或示例

    我正在尝试在 Struts 中制作一个登录页面 这个想法是验证用户是否存在等 然后如果有错误 则返回到登录页面 错误显示为红色 典型的登录或任何表单页面验证 我想知道是否有人知道 Struts 中的错误管理教程 我正在专门寻找有关的教程 或
  • 从一个文本文件中获取数据并将其移动到新的文本文件

    我有一个文件 里面有数据 在我的主要方法中 我读入文件并关闭文件 我调用另一种方法 在原始文件的同一文件夹内创建一个新文件 所以现在我有两个文件 原始文件和通过我调用的方法生成的文件 我需要另一种方法 从原始文件中获取数据并将其写入创建的新
  • 为什么 BufferedWriter 不写入文件?

    我有这个代码 String strings Hi You He They Tetrabenzene Caaorine Calorine File file new File G words txt FileWriter fWriter Bu

随机推荐

  • flask获取post参数_Flask教程2:模板

    什么是模板 模板负责定义页面的显示样式 与应用的逻辑相互独立 在Flask中 模板放在templates文件夹 是单独的html文件 编写一个模板 在app文件夹内创建templates文件夹 并新建index html文件 用来显示用户的
  • sqlilabs第26a

    sqlilabs第26a 一 手注 有错误希望师傅们指出 一 手注 直接看源码 无回显 我使用boolean盲注 过滤了and 空格 注释 空格可以通过 或者 0a绕过 and可以用 或者双写绕过 但这道题 不行 注释使用 1 1闭合 判断
  • Apache Druid远程代码执行漏洞复现(CVE-2021-25646)

    Apache Druid远程代码执行漏洞复现 CVE 2021 25646 漏洞描述 Apache Druid包括执行用户提供的JavaScript的功能嵌入在各种类型请求中的代码 此功能在用于高信任度环境中 默认已被禁用 但是 在Drui
  • 39天前端入门教程,免费领!!还送原创书籍+限量鼠标垫

    39天前端入门教程课程内容 福利 课程包含完整视频 笔记 源码 开发工具 39天前端入门教程 免费领 还送原创书籍 限量鼠标垫 关注 黑马程序员视频库 回复518 即可免费领取哦
  • mysql对姓名、手机号、身份证号做脱敏处理

    SELECT phone手机号脱敏处理 IF phone CONCAT LEFT phone 3 RIGHT phone 4 AS dephone cardno身份证号脱敏处理 IF cardno CONCAT LEFT cardno 3
  • 小甲鱼python视频xxoo爬虫代码改进--煎蛋网

    2020 7 31 今天学习得是关于小甲鱼得python课程 根据这个课程也确确实实得学到了不少东西 所以希望大家也可以一起去学习 下面是我在小甲鱼上课改造之后得代码 这个课程是在b站上看的 号码是 av27789609 这个是第五十节左右
  • Flutter入门学习(二)第一个Flutter应用

    Flutter 开发环境搭建好之后 创建第一个Flutter应用 使用VSCode来创建第一个Flutter应用 打开 VSCode 后 Cmd Shift p 选择 Flutter New Project 即可创建 如下图 如果右下角报找
  • hdu 1058 Humble Numbers

    Problem acm hdu edu cn showproblem php pid 1058 题意 找出从小到大第 n 个因子 除了 1 和本身 只有 2 3 5 7 的数 即第 n 个 num 2 a 3 b 5 c 7 d 的数 据说
  • com.google.common不存在

    无法导入com google common包 解决办法 在gradle添加依赖 implementation com google guava guava 16
  • 基于应力的拓扑优化的高效3D灵敏度分析代码(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 本文包括基于伴随方法的有限元分析和 p 范
  • ROS直接pub compressed image.

    如果用ros的 image transport Publisher 发布图片的话则 ros会自动添加一个 image compressed的topic 将原始图像编码 编码方式可以设置为png jpeg 有时候我们获取到的图片就是编码之后的
  • javascript作用域

    原文地址 http wenku baidu com view a4290ad9ce2f0066f5332229 html 关于js的作用域链 早有耳闻 也曾看过几篇介绍性的博文 但一直都理解的模棱两可 近日又精心翻看了一下 悟透Javasc
  • 订单系统、报名、预约、表单系统 定制开发功能展示

    安装教程环境说明 正常情况下PHP5 3 5 6 阿帕奇 mysql安装即可 安装说明 1 上传源码压缩包到网站根目录 这个请去问下空间商哪个是根目录 每家服务器商不一样 我们也不能确定 请确定是根目录再安装 2 解压源码到根目录然后打开网
  • Qt TableWidget插入QComboBox下拉框

    话不多说 以下是效果图 直接上代码 初始化QTableWidget Function partTableInit Description 初始化tablewidget 并设置表头列文字 Input QTableWidget tableObj
  • Failed to calculate the value of task ‘:xxx DebugJavaWithJavac‘ property ‘options.generatedSourceOut

    Caused by org gradle api internal provider AbstractProperty PropertyQueryException Failed to calculate the value of task
  • LightGBM的黑科技--plot函数

    本教程教萌新如何使用lightgbm里面可视化函数 作者 JasonChen 文章内容概览 保留训练结果 plot metric 函数的使用 重要 plot importance 函数的使用 重要 plot tree 函数的使用 可选 cr
  • Iterator对象

    Iterator对象 是一个引用型变量 他存在的意义在于 为了遍历容器对象中的元素而不暴露容器对象内部的细节 iterator 方法是容器变量使用 返回一个Iterator对象 该对象也是一个容器 因为他里面存放着即将访问的容器对象的元素
  • python怎么统计单词总数_利用Python的 counter内置函数,统计文本中的单词数量

    counter是 colletions内的一个类 可以理解为一个简单的计数器 可以统计字符出现的个数 例子如下 importcollections str1 a a b d m collections Counter str1 print
  • SSD算法详解 及其 keras实现 (下)

    在上一篇的博客讲述了SSD的原理 这一篇主要是讲解keras的实现 keras代码的github地址为 点击打开链接 model 的框架实现 ssd py 先给出了改变后的VGG16的实现 def SSD300 input shape nu
  • MybatisPlus多表连接查询

    一 序言 一 背景内容 软件应用技术架构中DAO层最常见的选型组件为MyBatis 熟悉MyBatis的朋友都清楚 曾几何时MyBatis是多么的风光 使用XML文件解决了复杂的数据库访问的难题 时至今日 曾经的屠龙者终成恶龙 以XML文件