MyBatis Dynamic SQL基本使用

news2024/12/23 23:46:35

MyBatis Dynamic SQL基本使用

  • 一、概念
  • 二、特性
      • Hamcrest是什么
  • 三、MyBatis Dynamic SQL 快速入门
    • 3.1 环境准备
    • 3.2 定义表和列
    • 3.3 创建 MyBatis3 映射器
    • 3.4 使用 MyBatis3 执行 SQL
  • 四、数据库对象表示
    • 4.1 表或视图表示
    • 4.2 表别名
    • 4.3 列表示
  • 五、Where 子句支持
    • 5.1 简单的 where 子句
    • 5.2 复杂的 where 子句
    • 5.3 子查询
    • 5.4 独立的 where 子句
  • 六、select 语句
    • 6.1 join
    • 6.2 联合查询
    • 6.3 多选查询
  • 七、运行机制

在这里插入图片描述

一、概念

该库是一个用于生成动态 SQL 语句的框架。将其视为类型安全的 SQL 模板库, 并提供对 MyBatis3Spring JDBC模板的额外支持。
该库通过实现类似 SQLDSL 来工作,该 DSL 创建一个包含完整 SQL 语句以及该语句所需的任何参数的对象。SQL 语句对象可以被 MyBatis 直接用作 mapper方法的参数。

二、特性

  1. 类型安全
  2. 富有表现力(语句的构建方式可以清楚地传达其含义,灵感来自 Hamcrest
  3. 灵活
  4. 可扩展性
  5. 占用小(该库是一个需要添加的小依赖项。它没有传递依赖)

Hamcrest是什么

Hamcrest 是一个用于编写匹配器(matcher)对象的框架,它允许以声明方式定义“匹配(match)”规则。这个框架主要用于编写断言,以便于在单元测试中进行使用。Hamcrest 提供了一系列可重用的断言和匹配器,使得编写测试更加简单和直观。它是一个Java库,能组合成灵活的表达式,以测试为目的,用于编写断言和匹配器。

三、MyBatis Dynamic SQL 快速入门

使用 MyBatis 动态 SQL 需要一下步骤:

  1. 创建表和列对象
  2. (对于 MyBatis3 )创建映射器(基于 XMLJava
  3. 编写和使用 SQL

3.1 环境准备

create table Person (
    id int not null,
    first_name varchar(30) not null,
    last_name varchar(30) not null,
    birth_date date not null,
    employed varchar(3) not null,
    occupation varchar(30) null,
    address_id int not null,
    primary key(id)
);
package examples.simple;

import java.util.Date;

public class PersonRecord {
    private Integer id;
    private String firstName;
    private LastName lastName;
    private Date birthDate;
    private Boolean employed;
    private String occupation;
    private Integer addressId;

    // getters and setters omitted
}

3.2 定义表和列

该类org.mybatis.dynamic.sql.AlisableSqlTable 用于定义表。表定义包括表的实际名称(如果使用,包括模式或目录)。如果需要,可以在 select 语句中应用表别名。您的表应该通过扩展 AlisableSqlTable<T>类来定义。该类org.mybatis.dynamic.sql.SqlColumn用于定义库中使用的列。列定义包括:

  1. Java 类型
  2. 实际的列名(可以在 select 语句中应用别名)
  3. JDBC 类型
  4. (可选)如果不需要默认类型处理程序,则在 MyBatis 中使用的类型处理程序的名称
package examples.simple;

import java.sql.JDBCType;
import java.util.Date;

import org.mybatis.dynamic.sql.SqlColumn;
import org.mybatis.dynamic.sql.AliasableSqlTable;

public final class PersonDynamicSqlSupport {
    public static final Person person = new Person();
    public static final SqlColumn<Integer> id = person.id;
    public static final SqlColumn<String> firstName = person.firstName;
    public static final SqlColumn<LastName> lastName = person.lastName;
    public static final SqlColumn<Date> birthDate = person.birthDate;
    public static final SqlColumn<Boolean> employed = person.employed;
    public static final SqlColumn<String> occupation = person.occupation;
    public static final SqlColumn<Integer> addressId = person.addressId;

    public static final class Person extends AliasableSqlTable<Person> {
        public final SqlColumn<Integer> id = column("id", JDBCType.INTEGER);
        public final SqlColumn<String> firstName = column("first_name", JDBCType.VARCHAR);
        public final SqlColumn<LastName> lastName = column("last_name", JDBCType.VARCHAR, "examples.simple.LastNameTypeHandler");
        public final SqlColumn<Date> birthDate = column("birth_date", JDBCType.DATE);
        public final SqlColumn<Boolean> employed = column("employed", JDBCType.VARCHAR, "examples.simple.YesNoTypeHandler");
        public final SqlColumn<String> occupation = column("occupation", JDBCType.VARCHAR);
        public final SqlColumn<Integer> addressId = column("address_id", JDBCType.INTEGER);

        public Person() {
            super("Person", Person::new);
        }
    }
}

3.3 创建 MyBatis3 映射器

该库将创建用作 MyBatis 映射器输入的类。这些类包括生成的 SQL 以及生成的 SQL 相匹配的参数集。两者都是 MyBatis 所需要的。这些对象旨在成为 MyBatis 映射器方法的唯一参数。
该库可以与 XML 和带注解的映射器一起使用,但我们建议在所有情况下都使用 MyBatis 的带注解的映射器支持。唯一需要 XML 的情况是当您编写 Join 语句时,在这种情况下,由于 MyBatis 注解在支持连接方面的限制,您将需要在 XML 中定义结果映射。

package examples.simple;

import java.util.List;
import java.util.Optional;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.mybatis.dynamic.sql.util.SqlProviderAdapter;
import org.mybatis.dynamic.sql.util.mybatis3.CommonCountMapper;
import org.mybatis.dynamic.sql.util.mybatis3.CommonDeleteMapper;
import org.mybatis.dynamic.sql.util.mybatis3.CommonInsertMapper;
import org.mybatis.dynamic.sql.util.mybatis3.CommonUpdateMapper;

@Mapper
public interface PersonMapper extends CommonCountMapper, CommonDeleteMapper, CommonInsertMapper<PersonRecord>, CommonUpdateMapper {

    @SelectProvider(type = SqlProviderAdapter.class, method = "select")
    @Results(id = "PersonResult", value = {
            @Result(column = "A_ID", property = "id", jdbcType = JdbcType.INTEGER, id = true),
            @Result(column = "first_name", property = "firstName", jdbcType = JdbcType.VARCHAR),
            @Result(column = "last_name", property = "lastName", jdbcType = JdbcType.VARCHAR, typeHandler = LastNameTypeHandler.class),
            @Result(column = "birth_date", property = "birthDate", jdbcType = JdbcType.DATE),
            @Result(column = "employed", property = "employed", jdbcType = JdbcType.VARCHAR, typeHandler = YesNoTypeHandler.class),
            @Result(column = "occupation", property = "occupation", jdbcType = JdbcType.VARCHAR),
            @Result(column = "address_id", property = "addressId", jdbcType = JdbcType.INTEGER)
    })
    List<PersonRecord> selectMany(SelectStatementProvider selectStatement);

    @SelectProvider(type = SqlProviderAdapter.class, method = "select")
    @ResultMap("PersonResult")
    Optional<PersonRecord> selectOne(SelectStatementProvider selectStatement);
}

该映射器为表实现了完整的 CRUD 功能。基本接口 CommonCountMapperCommonDeleteMapper 等提供插入、更新、删除和计数功能。由于自定义结果映射,只需编写 select 方法。请注意,CommonInsertMapper 如果插入生成了主键key,则接口将无法正确返回生成的主键key。

3.4 使用 MyBatis3 执行 SQL

在服务类中,您可以使用生成的语句作为映射器方法的输入。

@Test
void testGeneralSelect() {
    try (SqlSession session = sqlSessionFactory.openSession()) {
        PersonMapper mapper = session.getMapper(PersonMapper.class);

        SelectStatementProvider selectStatement = select(id.as("A_ID"), firstName, lastName, birthDate, employed,
            occupation, addressId)
        .from(person)
        .where(id, isEqualTo(1))
        .or(occupation, isNull())
        .build()
        .render(RenderingStrategies.MYBATIS3);

        List<PersonRecord> rows = mapper.selectMany(selectStatement);
        assertThat(rows).hasSize(3);
    }
}

@Test
void testGeneralDelete() {
    try (SqlSession session = sqlSessionFactory.openSession()) {
        PersonMapper mapper = session.getMapper(PersonMapper.class);

        DeleteStatementProvider deleteStatement = deleteFrom(person)
        .where(occupation, isNull())
        .build()
        .render(RenderingStrategies.MYBATIS3);

        int rows = mapper.delete(deleteStatement);
        assertThat(rows).isEqualTo(2);
    }
}

四、数据库对象表示

MyBatis Dynamic SQL 使用代表关系表或视图的 Java 对象。

4.1 表或视图表示

org.mybatis.dynamic.sql.SqlTable 类用于表示数据库中的表或视图。 SqlTable 包含一个名称,以及代表表或视图中的列的 SqlColumn 对象的集合。
SQL 中的表或视图名称由三个部分组成:

  1. The catalog :可选,很少在 SQL Server 之外使用。如果未指定,将使用默认目录,许多数据库只有一个目录。
  2. The schema :可选,架构名或者库名。如果未指定,将使用默认架构或库名。
  3. The table name:必选,表名。

例如:

  • dbo..bar” :dbo目录下的表名为 bar 的表。(SQL Server中使用)
  • foo.bar” :模式名或者库名为 foo 下的 bar 表。
  • “bar” :表名为 bar 的表。

在 MyBatis Dynamic SQL 中,表的全名应该在表对象的构造函数中提供。如果表名称需要在运行时更改(例如分片支持),则使用 withName 方法 AliasableSqlTable 以新名称创建实例。

我们建议在所有情况下都使用基类,AliaableSqlTable 因为它提供了最大的灵活性。该类 SqlTable 保留在库中只是为了与旧代码兼容。
例如:

import org.mybatis.dynamic.sql.AliasableSqlTable;

public class MyTable extends AliasableSqlTable<MyTable> {
    public MyTable() {
        super("MyTable", MyTable::new);
    }
}

或者

public class MyTable extends AliasableSqlTable<MyTable> {
    public MyTable() {
        super("MySchema.MyTable", MyTable::new);
    }
}

您可以更改表名称:

public class MyTable extends AliasableSqlTable<MyTable> {
    public MyTable() {
        super("Schema1.MyTable", MyTable::new);
    }
}

MyTable schema1Table = new MyTable();
MyTable schema2Table = schema1Table.withName("Schema2.MyTable");

4.2 表别名

在连接查询中,指定表别名通常是一个好习惯。该select语句支持以类似于自然 SQL 的方式在每个查询中指定表别名。

SelectStatementProvider selectStatement = 
            select(
                orderMaster.orderId,
                orderDate,
                orderLine.lineNumber,
                itemMaster.description,
                orderLine.quantity)
            .from(orderMaster, "om")
            .join(orderLine, "ol").on(orderMaster.orderId, equalTo(orderLine.orderId))
            .join(itemMaster, "im").on(orderLine.itemId, equalTo(itemMaster.itemId))
            .where(orderMaster.orderId, isEqualTo(2))
            .build()
            .render(RenderingStrategies.MYBATIS3);

在这样的查询中,当呈现查询时,库会自动将表别名附加到列名称中。在内部,列别名是通过在查询模型中维护的 HashMap 中查找关联表来确定的。如果不指定表别名,库将自动在连接查询中附加表名称。(但是不推荐这种,因为自连接的时候会有问题)
从版本 1.3.1 开始,有一个新方法,可以在表对象本身中指定别名。

User user1 = user.withAlias("u1");
User user2 = user.withAlias("u2");

SelectStatementProvider selectStatement = 
        select(
            user1.userId,
            user1.userName,
            user1.parentId)
        .from(user1)
        .join(user2).on(user1.userId, equalTo(user2.parentId))
        .where(user2.userId, isEqualTo(4))
        .build()
        .render(RenderingStrategies.MYBATIS3);

要启用此支持,您的表对象应该扩展 org.mybatis.dynamic.sql.AliasableSqlTable 而不是 org.mybatis.dynamic.sql.SqlTable 如下所示:

public static final class User extends AliasableSqlTable<User> {
    public final SqlColumn<Integer> userId = column("user_id", JDBCType.INTEGER);
    public final SqlColumn<String> userName = column("user_name", JDBCType.VARCHAR);
    public final SqlColumn<Integer> parentId = column("parent_id", JDBCType.INTEGER);

    public User() {
        super("User", User::new);
    }
}

如果使用别名表对象,并且还在 select 语句中指定别名,则语句中的别名 select 将覆盖表对象中的别名。

4.3 列表示

该类 org.mybatis.dynamic.sql.SqlColumn 用于表示表或视图中的列。一个 SqlColumn 始终相关联一个 SqlTable
该类 SqlColumn 具有额外的可选属性,对于 SQL 渲染非常有用——尤其是在 MyBatis3 中。这些包括:

  • 列的 JDBC 类型 : java.sql.JDBCType 。这将被渲染到 MyBatis3 兼容的参数标记中,这有助于选择类型处理程序以及插入或更新支持 null 的字段。
  • 包含类型处理程序的字符串: 类型处理程序别名或类型处理程序的完全限定类型。这将被渲染到 MyBatis3 兼容参数标记中。

五、Where 子句支持

该库支持创建非常灵活的 where 子句。

5.1 简单的 where 子句

最简单的 where 子句的形式如下:

SelectStatementProvider selectStatement = select(count())
                .from(simpleTable)
                .where(id, isEqualTo(3))
                .build()
                .render(RenderingStrategies.MYBATIS3);

该库附带了可在 where 子句中使用的各种条件,包括inlikebetweenisNullisNotNull 和所有正常的比较运算符。例如:

 SelectStatementProvider selectStatement = select(count())
                .from(simpleTable)
                .where(id, isBetween(3).and(6))
                .build()
                .render(RenderingStrategies.MYBATIS3);

 SelectStatementProvider selectStatement = select(count())
                .from(simpleTable)
                .where(id, isIn(3,4,5))
                .build()
                .render(RenderingStrategies.MYBATIS3);

SelectStatementProvider selectStatement = select(count())
                .from(simpleTable)
                .where(id, isNotNull())
                .build()
                .render(RenderingStrategies.MYBATIS3);

5.2 复杂的 where 子句

条件实际上可以以任何组合进行“与”和“或”组合。例如:

 SelectStatementProvider selectStatement = select(count())
                .from(simpleTable, "a")
                // isGreaterThan(2) -> id > 2
                .where(id, isGreaterThan(2))
                .or(occupation, isNull(), and(id, isLessThan(6)))
                .build()
                .render(RenderingStrategies.MYBATIS3);

5.3 子查询

SelectStatementProvider selectStatement = select(column1.as("A_COLUMN1"), column2)
                .from(table, "a")
                .where(column2, 
                       isIn(
                            select(column2)
                           .from(table)
                           .where(column2, isEqualTo(3))
                       ))
                .or(column1, isLessThan(d))
                .build()
                .render(RenderingStrategies.MYBATIS3);

5.4 独立的 where 子句

尽管很少见,但如果您希望为语句的其余部分编写自己的 SQL,则可以单独使用 where 子句支持。这样做可能有多种原因 - 主要是如果库不支持您想要使用的某些 SQL 或 MyBatis 功能。一个很好的例子是,如果您想将其他 SQL 附加到库生成的 SQL 中。如果您想使用独立的 where 子句,您可以编写如下所示的映射器方法:

@Select({
        "select id, animal_name, brain_weight, body_weight",
        "from AnimalData",
        "${whereClause}"
    })
    @ResultMap("AnimalDataResult")
    List<AnimalData> selectWithWhereClause(WhereClauseProvider whereClause);

您可以构建一个独立的 where 子句并像这样调用您的映射器:

Optional<WhereClauseProvider> whereClause = where(id, isNotBetween(10).and(60))
            .build()
            .render(RenderingStrategies.MYBATIS3);

    List<AnimalData> animals = whereClause.map(wc -> mapper.selectWithWhereClause(wc)).orElse(Collections.emptyList());

当语句不需要其他参数并且不涉及表别名时,此方法效果很好。

六、select 语句

  1. select 语句的典型部分包括 selectdistinctfromjoinwheregroup byunion allorder byhaving
  2. 每个 select 语句可以为表设置别名
  3. 每个 select 语句可以为列指定别名
  4. 对聚合的一些支持(平均值、最小值、最大值、总和)
  5. innerleft outerright outerfull outer类型的等连接
  6. where 子句中的子查询。例如,where foo in (select foo from foos where id < 36)
  7. 从另一个 select 中 select 。例如,select count(*) from (select foo from foos where id < 36)
  8. 多选。例如(select * from foo order by id limit 3) union (select * from foo order by id desc limit 3)

目前,该库不支持以下内容:

  1. 带表达式
  2. 相交、除外等
SelectStatementProvider selectStatement = select(id, animalName, bodyWeight, brainWeight)
        .from(animalData)
        .where(id, isIn(1, 5, 7))
        .and(bodyWeight, isBetween(1.0).and(3.0))
        .orderBy(id.descending(), bodyWeight)
        .build()
        .render(RenderingStrategies.MYBATIS3);

List<AnimalData> animals = mapper.selectMany(selectStatement);

6.1 join

该库支持生成等值连接语句,通过列匹配定义的连接。例如:

 SelectStatementProvider selectStatement = select(orderMaster.orderId, orderDate, orderDetail.lineNumber, orderDetail.description, orderDetail.quantity)
            .from(orderMaster, "om")
            .join(orderDetail, "od").on(orderMaster.orderId, equalTo(orderDetail.orderId))
            .build()
            .render(RenderingStrategies.MYBATIS3);

请注意,如果需要,您可以为表指定别名。如果不指定别名,则生成的 SQL 中将使用完整的表名。
可以在一条语句中连接多个表。例如:

 SelectStatementProvider selectStatement = select(orderMaster.orderId, orderDate, orderLine.lineNumber, itemMaster.description, orderLine.quantity)
            .from(orderMaster, "om")
            .join(orderLine, "ol").on(orderMaster.orderId, equalTo(orderLine.orderId))
            .join(itemMaster, "im").on(orderLine.itemId, equalTo(itemMaster.itemId))
            .where(orderMaster.orderId, isEqualTo(2))
            .build()
            .render(RenderingStrategies.MYBATIS3);

连接查询可能需要您在 XML 中定义 MyBatis 结果映射。这是唯一需要 XML 的实例。这是由于 MyBatis 注解在映射集合时的限制造成的。
该库支持四种连接类型:

  1. .join(...)是一个 INNER 连接
  2. .leftJoin(...)是 LEFT OUTER 连接
  3. .rightJoin(...)是 RIGHT OUTER 连接
  4. .fullJoin(...)是一个 FULL OUTER 连接

6.2 联合查询

该库支持生成 union 和 union all 查询。例如:

SelectStatementProvider selectStatement = select(id, animalName, bodyWeight, brainWeight)
        .from(animalData)
        .union()
        .selectDistinct(id, animalName, bodyWeight, brainWeight)
        .from(animalData)
        .orderBy(id)
        .build()
        .render(RenderingStrategies.MYBATIS3);

可以将任意数量的 SELECT 语句添加到 UNION 查询中。只允许使用一个 ORDER BY 短语。
对于这种类型的联合查询,“order by”和分页子句作为一个整体应用于查询。如果需要对嵌套查询应用“order by”或分页子句,请使用多选查询,如下所示。

6.3 多选查询

多选查询时联合 select 语句的一种特殊情况。不同之处在于“order by”和分页子句可以应用于合并查询。例如:

 SelectStatementProvider selectStatement = multiSelect(
            select(id, animalName, bodyWeight, brainWeight)
            .from(animalData)
            .orderBy(id)
            .limit(2)
        ).union(
            selectDistinct(id, animalName, bodyWeight, brainWeight)
            .from(animalData)
            .orderBy(id.descending())
            .limit(3)
        )
        .build()
        .render(RenderingStrategies.MYBATIS3);

七、运行机制

MyBatis 主要做了四件事:

  1. 它安全地执行 SQL 并抽象出 JDBC 的所有复杂性
  2. 它将参数对象映射到 JDBC 准备好的语句参数
  3. 它将 JDBC 结果集中的行映射到对象
  4. 它可以通过 XML 中的特殊标签生成动态SQL,或者通过使用各种模板引擎

该库充分利用了 MyBatis 中的前三个功能,本质上成为生成动态 SQL 的另一个模板引擎。
例如,MyBatis 可以执行如下格式的 SQL 字符串:

select id, description from table_codes where id = #{id,jdbcType=INTEGER}

这是带有 MyBatis 风格的标准 SQL, 参数符号 #{id,jdbcType=INTEGER} 告诉 MyBatis 获取 id参数对象的属性并将其用作 JDBC 准备好的语句参数。
现在假设我们有两个这样的 Java 类:

public class TableCode {
  private Integer id;
  private String description;
  ... getters/setters
}

public class Parameter {
  private String sql = "select id, description from table_codes where id = #{id,jdbcType=INTEGER}";
  private Integer id;

  public Parameter(Integer id) {
    this.id = id;
  }

  public Integer getId() {
    return id;
  }

  public String getSql() {
    return sql;
  }
}

这些类可以与 MyBatis 映射器结合使用,如下所示:

public interface Mapper {

  @Select({
    "${sql}"
  })
  TableCode getTableCode(Parameter parameter);
}

将此映射器与 MyBatis 一起使用如下所示:

try(SqlSession sqlSession = sqlSessionFactory.openSession()) {
    Mapper mapper = sqlSession.getMapper(Mapper.class);
    Parameter parameter = new Parameter(2);
    TableCode tableCode = mapper.getTableCode(parameter);
    assertThat(tableCode.getId()).isEqualTo(2);
}

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

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

相关文章

什么样的文件传输调度产品 可以简化IT工作流程?

文件传输调度是企业数据管理中的一个重要环节&#xff0c;企业在存在多个分支机构、子公司&#xff0c;或者多个数据中心、服务器节点的时候&#xff0c;都会需要进行文件传输调度&#xff0c;在使用传统的FTP、rsync等传输方式在应对这些复杂的文件交换需求时&#xff0c;会存…

C语言趣味代码(三)

这一篇主要围绕写一个程序---寻找数字 来写&#xff0c;在这篇我会详细和大家介绍基本实现以及它的改良版&#xff0c;还有相关知识的拓展&#xff0c;干货绝对满满。 1. 寻找数字 在这一主题下&#xff0c;我们会编写一些代码&#xff0c;来锻炼玩家的反应力&#xff0c;同时…

让外贸客户心甘情愿下单的话术分享

学会这些话术&#xff0c;轻松拿捏客户&#xff0c;让客户心甘情愿下单 一、客户喜欢讨价还价的模板旨在帮助外贸人员在与客户讨价还价时&#xff0c;既能坚持自己的立场&#xff0c;又能体现出专业和诚信的态度。 二、客户犹豫要不要下单的贸易话术旨在帮助客户消除疑虑&#…

Spring Boot 源码--SpringApplication#run 方法源码解析

前言&#xff1a; 开发过 Spring Boot 项目的都知道只需要一个简单的入口类&#xff0c;然后入口类中有个 main 方法&#xff0c;main 方法中调用了 SpringApplication.run 方法&#xff0c;再配合 SpringBootApplication 注解就可以完成一个项目的启动&#xff0c;如下&#…

云打印怎么上传文件?云打印怎么把文件发送给商家?

随着云打印的火热&#xff0c;现在很多同学们都选择云打印服务来打印自己的资料文档。但是云打印服务毕竟要隔着网络打印&#xff0c;那么我们应该怎么上传文件呢&#xff1f;云打印怎么把文件发送给商家呢&#xff1f;今天小易就带大家一起来了解一下。 云打印怎么上传文件&am…

python爬虫之xpath4

1 最终项目实现的代码 仙剑 #!/usr/bin/env python ​ import logging import requests import re from urllib.parse import urljoin import pymongo import multiprocessing ​ mongo_client pymongo.MongoClient("mongodb://192.168.135.131:27017/") db mong…

【禅道客户案例】专访鸿泉物联研发副总监徐小倩,感受上市公司研发项目管理“知与行”

杭州鸿泉物联网技术股份有限公司&#xff08;以下简称“鸿泉物联”、“公司”&#xff09;成立于2009年6月11日&#xff0c;2019年11月6日登陆上海证券交易所科创板&#xff08;股票代码&#xff1a;688288&#xff09;&#xff0c;注册资本10034.392万元&#xff0c;目前员工6…

嵌入式4-24

作业&#xff1a; 整理思维导图 定义一个矩形类Rec&#xff0c;包含私有属性length&#xff0c;width&#xff0c;有以下成员函数&#xff1a; void set_length(int l); //设置长度 void set_width(int w); //设置宽度 int get_length(); //获取长度 int get_width(); //获取宽…

Julia教程(一):变量

1、变量 在 Julia 中&#xff0c;变量是与值关联&#xff08;或绑定&#xff09;的名称。当想要存储一个值&#xff08;例如&#xff0c;经过一些数学运算后获得的值&#xff09;以供以后使用时&#xff0c;它非常有用。例如&#xff1a; # 定义一个变量x&#xff0c;并赋值为…

力扣:82. 删除排序链表中的重复元素 II(Java)

目录 题目描述&#xff1a;输入&#xff1a;输出&#xff1a;代码实现&#xff1a; 题目描述&#xff1a; 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 输入&#xff1a; head [1,2,3…

AXI4---低功耗接口

在电子系统设计中&#xff0c;"low-power interface"&#xff08;低功耗接口&#xff09;是指专为减少能耗而设计的硬件接口。这类接口在不需要牺牲性能的情况下&#xff0c;通过各种技术降低功耗&#xff0c;对于移动设备、嵌入式系统和其他电池供电的应用来说尤其重…

为什么要使用gamma校正?

为什么要使用gamma校正&#xff1f; 人眼直接观察实物相机拍摄、存储、输出到显示器上&#xff0c;人眼再观察该物体1. 拍摄2. 存储3. 显示 总结&#xff1a;在计算机时代早期&#xff0c;为了抵消当时主流的RTC显示器的非线性特征&#xff0c;拍摄图片存储过程中需要gamma校正…

蓝桥杯-网络安全-练习题-crypto-rsa

共模攻击 直接脚本即可 import libnum import gmpy2import random random.seed(123456)e1 random.randint(100000000, 999999999) print(e1) e2 65537 n 7265521127830448713067411832186939510560957540642195787738901620268897564963900603849624938868472135068795683…

【blog项目】layui与jquery冲突导致鼠标悬停事件失效、如何调用layui.use()作用域里的方法

blog项目前台展示——查询数据库中的文章类型并展示时出现的bug 1 正常演示 2 用jquery查询数据库并添加到页面后 3 相关代码 <script src"/static/jquery-2.1.4.js"></script> <script src"/static/layui/layui.js"></script> …

信息系统项目管理师——质量管理论文写法以及子题目

质量管理概论 过程组过程名称含义输入工具和技术输出规划过程组规划质量管理制定质量管理策略、明确质量标准与过程&#xff0c;以确保项目满足既定质量要求。- 项目管理计划- 干系人登记册- 需求文档- 组织过程资产1.专家判断 2.数据收集 标杆对照 头脑风暴 访谈 3.数据分析 …

【网络安全】跨站脚本攻击(XSS)

专栏文章索引&#xff1a;网络安全 有问题可私聊&#xff1a;QQ&#xff1a;3375119339 目录 一、XSS简介 二、XSS漏洞危害 三、XSS漏洞类型 1.反射型XSS 2.存储型XSS 3.DOM型XSS 四、XSS漏洞防御 一、XSS简介 XSS&#xff08;Cross-Site Scripting&#xff09; XSS 被…

机器视觉系统-工业光源什么是高角度光,以及发光角度得分类

光路描述&#xff1a;光线与水平面角度>45称为高角度光。 效果分析&#xff1a;高角度照射&#xff0c;光线经 被测物表面平整部分反射后进入镜头&#xff0c;图像效果表现为灰度值较高&#xff1b;不平整部分反射光进入不了镜头&#xff0c;图像效果表现为灰度值较低。 主要…

高薪诱惑下,跳槽真的是明智选择吗?

跳槽是职场生涯中不可避免的一部分&#xff0c;许多人在考虑是否换工作时&#xff0c;往往会被潜在的高薪所吸引。然而&#xff0c;决定是否接受一个高薪职位的邀请并非易事&#xff0c;它涉及到多个层面的权衡和考量。 我们要认识到薪酬仅是工作回报的一个方面。虽然高薪资往往…

springboot:java操作docker(docker-java)的基本使用

文章目录 dokcer-java使用xmlping拉取镜像创建容器查看所有容器信息启动容器查看日志删除容器删除镜像 dokcer-java使用 xml 引入依赖 <!-- https://mvnrepository.com/artifact/com.github.docker-java/docker-java --> <dependency><groupId>com.github…

【漏洞复现】通天星CMSV6车载监控平台Login弱口令漏洞

漏洞描述&#xff1a; 通天星CMSV6车载定位监控平台拥有以位置服务、无线3G/4G视频传输、云存储服务为核心的研发团队&#xff0c;专注于为定位、无线视频终端产品提供平台服务&#xff0c;通天星CMSV6产品覆盖车载录像机、单兵录像机、网络监控摄像机、行驶记录仪等产品的视频…