当前位置: 首页 > news >正文

CRUD-SQL

文章目录

  • 前置
      • insertSelective和upsertSelective使用姿势
      • 手写sql,有两种方式
  • 一、增
      • 当导入的数据不存在时则进行添加,有则更新
    • 1.1 唯一键,先查,后插
    • 1.2 批量插
      • 1.2.1 批次一200、批次二200、批次三200,有一条数据写入失败了
      • 1.2.2 要插入的数据 和 db中已经存在的数据进行求差集,不在db的数据才插入
      • 1.2.3 Column 'x' cannot be null
      • 1.2.4记录批量写【增、改】成功的int count值
  • 二、改
    • 2.1 updateByExampleSelective:未制定的表的列,属性不会进行更改
    • 2.2 :updateByExample:未执行值的列,会被置为null
    • 2.3 乐观锁
    • 2.4 普通修改
    • 2.5 批量修改
      • 2.6 updateByPrimaryKeySelective
      • 2.7 将ids们的某些字段值进行修改
  • 三、查
      • 前要:常见三种查询
    • 3.0 强制走索引
    • 3.1 普通查询
    • 3.2 查询的PO中字段含有text属性的数据时,选择selectByExampleWithBLOBs
      • 3.3 深分页问题
    • 3.4 selectByExampleWithRowBounds:不是真正意义上的分页查询,底层并没有分野查询。会扫面全量数据
      • 1、selectByExample
    • 3.5 走主库查
    • 3.6 一个查询条件作为一个key形式去查询(防止过多的in条件,导致笛卡尔乘积),使用OR的形式
  • 四、其它
    • 4.1 example中criteria对同一个字段赋值不会覆盖前一个值。

前置

insertSelective和upsertSelective使用姿势

  • 新增:insertSelective和upsertSelective

1、功能都是和手写sql的insert语句一样,都可以新增数据:未赋值的字段列,会使用default值赋值

普通的insert,未赋值的列如果是not null default ‘0’,则会报错

2、不同:如果表有唯一键,前者如果表中有了一条相同的数据,则插入报错,唯一键冲突;

后者,则选择的是on duplication key update即有相同的数据,则赋值了的字段也会被更新,未赋值的字段保持原值不变

  • 更新:updateByExampleSelective(等效人为写update sql) 和 upsertSelective

1、前者就是update where xxx语句,是更新语句。二者都可以更新字段,更新都是未赋值的字段不更新,仅更新赋值的字段

手写sql,有两种方式

1、在AutoMapper的子接口Mapper下,通过注解的形式

2、在AutoMapper的子接口Mapper下,通过xml的形式。只不过需要自己创建一个对应的xml【xml中前置内容,可参考AutoGeneratorMapper.xml中前置内容】

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper // 省略
</mapper>

一、增

当导入的数据不存在时则进行添加,有则更新

https://www.cnblogs.com/better-farther-world2099/articles/11737376.html

  @Insert("insert into lock_max_stock\n" +"    (id, net_poi_id, sale_date, sku_id, lock_type, status, rdc_id)\n" +"    values\n" +"    (#{id,jdbcType=BIGINT}, #{netPoiId,jdbcType=BIGINT}, #{saleDate,jdbcType=VARCHAR}, #{skuId,jdbcType=BIGINT}, \n" +"    #{lockType,jdbcType=INTEGER}, #{status,jdbcType=INTEGER}, #{rdcId,jdbcType=BIGINT})\n" +"    on duplicate key update \n" +"    status = #{status,jdbcType=INTEGER} \n")int upsertByKey(LockMaxStockDO lockMaxStockDO);

1.1 唯一键,先查,后插

        //唯一键poiId+containerFlowNo+pickingTaskNo校验List<ContainerPickingTask> existContainerPickingTasks = containerPickingTaskRepository.queryRelatedPickingTaskList(poiId, containerFlowNo, pickingTaskNo);if (null != existContainerPickingTasks && existContainerPickingTasks.size() > 0) {log.warn("已存在容器与拣货任务绑定关系,无需重复绑定,containerCode={}, containerFlowNo={}, pickingTaskNo={}.",containerCode, containerFlowNo, pickingTaskNo);throw new BusinessException(BUSINESS_ERROR, "已存在拣货任务与容器绑定");}
//没有再insertreturn containerPickingTaskRepository.insertContainerPickingTask(newContainerPickingTask);

幂等键

Optional<RefundSupplierMessage> messageOptional = refundSupplierMessageRepository.queryRefundSupplierMessage(message.getPoiId(), message.getRefundBillNo(), message.getMessageType());if (messageOptional.isPresent()) {// 如果已经发送过消息,则不用再次发送log.info("sendSupplierMessage...已经发送过消息,message:{}", messageString);} else {// 如果没有发送过消息,则发送try {rdcNotifySupplierStatusProducer.send(messageString, message.getPoiId(), DimType.RDC, message.getSupplierId());refundSupplierMessageRepository.insertRefundSupplierMessage(buildRefundSupplierMessage(message));} catch (Exception e) {}}

1.2 批量插

1.2.1 批次一200、批次二200、批次三200,有一条数据写入失败了

批次一200、批次二200、批次三200
场景1:不catch异常public void batchInsert(List<TestTableDO> DOList) {if (CollectionUtils.isEmpty(DOList)) {return;}Lists.partition(DOList, 200).forEach(partitionData -> {this.testTableAutoGeneratorMapper.batchInsert(partitionData);});}
1、同一个批次,插入多条数据时,是原子性的,一条失败,这个批次200条都失败,不会写入表中  
2、不同批次之间,没有原子性,报错的批次 以及 其后面的批次,都不会写入。报错之前的批次数据可正常插入
批次一失败,批次一中200条数据都不会写入。且后续批次二、三都不会执行
批次一成功,会插入200条数据,批次二中有失败,则批次二全部写入失败,批次三不会执行补充:现在id = 1,唯一键冲突,下一条数据的id = 1 + batchSize即200 = 201场景2catch吃掉异常public void batchInsertCatchException(List<TestTableDO> DOList) {if (CollectionUtils.isEmpty(DOList)) {return;}Lists.partition(DOList, 200).forEach(partitionData -> {//这里try的颗粒更小,在每个批次try。如果在最外层try了,批次1失败了,全部数据都会失败。后续的批次也不是执行了try {this.testTableAutoGeneratorMapper.batchInsert(partitionData);} catch (Exception e) {if (e instanceof DuplicateKeyException) {log.warn("测试数据,data:[{}]", GsonUtil.toJson(partitionData), e);} else {log.error("测试数据异常,data:[{}]", GsonUtil.toJson(partitionData), e);}}});1、同一个批次,插入多条数据时,是原子性的,一条失败,这个批次200条都失败,不会写入表中  
2、不同批次之间,没有原子性,只有报错的批次本身全部200条数据插入失败,其前面、后面批次均会写成功场景3:不catch异常 + 事务
@Service
public class TestService {@Resourceprivate ReturnSkuRepository returnSkuRepository;public void test(){//taskCode是唯一键TestTableDO d1 = TestTableDO.builder().taskCode("w5").poiId(323L).build();TestTableDO d2 = TestTableDO.builder().taskCode("w6").poiId(323L).build();TestTableDO d3 = TestTableDO.builder().taskCode("m3").poiId(323L).build();List<TestTableDO> testTableDOS = Lists.newArrayList(d1, d2, d3);returnSkuRepository.batchInsert(testTableDOS);//调用包含事务的方法batchInsert,不能和test方法在同一个类中,且batchInsert方法,必须是类的public方法}}public class ReturnSkuRepositoryImpl implement ReturnSkuRepository{@Resourceprivate TestTableAutoGeneratorMapper testTableAutoGeneratorMapper;@Override@Transactional(rollbackFor = DuplicateKeyException.class)public void batchInsert(List<TestTableDO> DOList) {if (CollectionUtils.isEmpty(DOList)) {return;}Lists.partition(DOList, 2).forEach(partitionData -> {this.testTableAutoGeneratorMapper.batchInsert(partitionData);});}
}
只要有一条数据插入失败,所有批次的所有数据,全部插入失败。即要么全成功,要么全失败补充:现在id = 1,唯一键冲突,下一条数据的id = 1 + 三个批次的全部数据-1 = 1+600 - 1 = 600SkuDOOrderDO一起 批量插入时
思路:如果想保持SkuOrder的 全部数据要么都成功,要么都失败。那就二者包在一个事务方法中,同时二者本身又在一个单独的事务方法中

每个数据的某个、某几个字段都是一样的(操作日期、这些sku都是用一个网店下的sku)

public interface SellOutWarnSkuMapper extends SellOutWarnSkuAutoGeneratorMapper {@Insert({"<script>","insert into sellout_warn_sku","(operation_day, sale_day, lot_code, warn_type, sku_id, net_poi_id, net_poi_name," +"      poi_id, sku_name, sku_supplier_id, sku_supplier_name, sku_price, sku_shelf_type, " +"      sku_temperature_level, sku_category_id, sku_all_category, base_predict_quantity, " +"      or_predict_quantity, sales_volume, sales_rate, max_sale_num," +"      operator, is_sellout, is_second_delivery, status, ctime, create_by)","values ","<foreach collection='list' item='item' separator=','>","(#{item.operationDay,jdbcType=VARCHAR}, #{item.saleDay,jdbcType=VARCHAR},#{item.lotCode,jdbcType=VARCHAR}, #{item.warnType,jdbcType=INTEGER}, #{item.skuId,jdbcType=BIGINT},#{item.netPoiId,jdbcType=BIGINT},#{item.netPoiName,jdbcType=VARCHAR},","#{item.poiId,jdbcType=BIGINT},#{item.skuName,jdbcType=VARCHAR}, #{item.skuSupplierId,jdbcType=BIGINT},#{item.skuSupplierName,jdbcType=VARCHAR}, #{item.skuPrice,jdbcType=DECIMAL}, #{item.skuShelfType,jdbcType=INTEGER},","#{item.skuTemperatureLevel,jdbcType=TINYINT},#{item.skuCategoryId,jdbcType=INTEGER}, #{item.skuAllCategory,jdbcType=VARCHAR},#{item.basePredictQuantity,jdbcType=DECIMAL},","#{item.orPredictQuantity,jdbcType=DECIMAL},#{item.salesVolume,jdbcType=DECIMAL}, #{item.salesRate,jdbcType=DECIMAL}, #{item.maxSaleNum,jdbcType=DECIMAL},","#{item.operator,jdbcType=VARCHAR},#{item.isSellout,jdbcType=INTEGER}, #{item.isSecondDelivery,jdbcType=INTEGER},#{item.status,jdbcType=INTEGER},#{item.ctime,jdbcType=TIMESTAMP},#{item.createBy,jdbcType=VARCHAR})","</foreach> ","on duplicate key update ","operation_day = values(operation_day),","sale_day = values(sale_day),","lot_code = values(lot_code),","net_poi_id = values(net_poi_id),","sku_id = values(sku_id)","</script>"})@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")int batchInsertReplace(@Param("list") List<SellOutWarnSkuDO> list);
}

1.2.2 要插入的数据 和 db中已经存在的数据进行求差集,不在db的数据才插入

 //01.根据db数据,过滤掉oih再次下发的相同sku数据Map<String, OriginReturnSkuDO> oihReturnSkuMap = new HashMap<>();Map<String, OriginReturnSkuDO> dbReturnSkuMap = new HashMap<>();batchInsertSkuDOS.forEach(originReturnSkuDO -> {String uniqueKey = originReturnSkuDO.getPackKey() + originReturnSkuDO.getSkuId() + originReturnSkuDO.getTaskCode();oihReturnSkuMap.put(uniqueKey, originReturnSkuDO);});dbReturnSkuDOList.forEach(originReturnSkuDO -> {String uniqueKey = originReturnSkuDO.getPackKey() + originReturnSkuDO.getSkuId() + originReturnSkuDO.getTaskCode();dbReturnSkuMap.put(uniqueKey, originReturnSkuDO);});// 02. 遍历oih获得的数据,如果数据在db中了则remove掉(这部分数据不能再插入了)Iterator<Map.Entry<String, OriginReturnSkuDO>> iterator = oihReturnSkuMap.entrySet().iterator();while (iterator.hasNext()) {Map.Entry<String, OriginReturnSkuDO> entry = iterator.next();String uniqueKey = entry.getKey();if (Objects.nonNull(dbReturnSkuMap.get(uniqueKey))) {//说明db中有这条数据了//过滤掉该条数据iterator.remove();log.warn("从oih获取到重复sku数据,uniqueKey:[{}]", uniqueKey);}}//03.存过滤后的sku至list,最终需要insert的数据List<OriginReturnSkuDO> finalInsertList = new ArrayList<>(oihReturnSkuMap.values());

1.2.3 Column ‘x’ cannot be null

1、背景:mysql中xxx字段not null default 0,在使用mybatis自动生成的insert语句时,未对xxx字段进行赋值,插入db时,报此错

2、原因:使用mybatis自动生成的insert,默认对所有字段进行插入。如果未对字段xxx赋值,相当于setXxx = null,即插入db时xxx字段为null,不满足not null所以报错

3、解决:

  • 使用mybatis的insert,给setXxx = 0

  • 自己写insert语句,sql语句中没有xxx字段,则在落表时,xxx会被默认值0

  • 使用mybatis的insertSelective

4、潜在风险点:

新需求需要新增字段y,如果设置y为not null default 0,那么就要评估代码中是否有使用mybatis的insert此表的逻辑

有的话,则需要给DO中y字段设置setY = 0,否则原本insert会报错:Column ‘y’ cannot be null

参考:https://www.cnblogs.com/sfnz/p/15618329.html

1.2.4记录批量写【增、改】成功的int count值

public int func(List<MyDO> doList) {return doList.partition(myDO, 200).stream().map(dos -> myapper.batchInsert(dos)).reduce(Integer::sum).orElse(0);}

二、改

2.1 updateByExampleSelective:未制定的表的列,属性不会进行更改

        //确认那些数据要改(where条件)RefundOutboundBillPOExample updateExample = new RefundOutboundBillPOExample();RefundOutboundBillPOExample.Criteria updateCriteria = updateExample.createCriteria();updateCriteria.andPoiIdEqualTo(poiId);updateCriteria.andRefundBillNoEqualTo(refundBillNo.trim());updateCriteria.andStatusEqualTo(preStatus.byteValue());updateCriteria.andValidEqualTo(Boolean.TRUE);//要改的具体内容setRefundOutboundBillPO refundOutboundBillPO = new RefundOutboundBillPO();refundOutboundBillPO.setChangeBy(operator);refundOutboundBillPO.setStatus(status.byteValue());refundOutboundBillPO.setChangeAt(new Date());try {int res = refundOutboundBillPoMapper.updateByExampleSelective(refundOutboundBillPO, updateExample);}

2.2 :updateByExample:未执行值的列,会被置为null

    int updateByExampleSelective(@Param("record") T record, @Param("example") E example);int updateByExample(@Param("record") T record, @Param("example") E example);

2.3 乐观锁

点击展开内容

场景1:

表中自带一些乐观锁性质的字段。比如状态status

A、B都能够看到,也都能够操作。就会出现并发问题。假如A先操作成功了update table set status= 23 where id = 1,将status状态改了。此时尽管B也进来操作了,update table set status= 23 where id = 1时,status状态已经改过了。所以update会失败。这种是乐观锁的效果

场景2:更新拣货规则, 通过乐观锁控制并发

  • 表中加乐观锁的字段。 version bigint(10) NOT NULL DEFAULT ‘1’ COMMENT ‘并发版本号’,

  • 类中:

    /*
    * 字段: ver_lock
    * 说明: 用于数据库乐观锁
    */
    *private Integer verLock;

    • update语句

      int affectLines = rulePOMapper.updateRule(rulePO);
      if (affectLines <= 0) {throw new BusinessException(Constants.SYSTEM_ERROR, "系统并发更新失败");
      }
      
          <update id="updateRule" parameterType="com.sankuai.grocerywms.logistics.sharedwos.dal.entity.RulePO">update ruleset rule_content = #{rule.ruleContent}, ver_lock=ver_lock+1<if test="rule.changeBy != null and rule.changeBy != ''">,change_by = #{rule.changeBy}</if>where poi_id = #{rule.poiId} and rule_no = #{rule.ruleNo} and ver_lock=#{rule.verLock} and valid=1</update>
      

      A、B同时进来,而且此时version=1。二人都有机会update

      此时A执行update: update table set k1=v1 ,k2=v2,version = version+1 where id = rule.id and version = #{rule.version}

      update table set k1 = v1,k2 = v2, version = version + 1 where id = 1 and version = 1
      

      A执行完sql语句后,id=1的数据,version=2了

      此时B执行sql语句,拿着version=1去执行

      update table set k1 = v1,k2 = v2, version = version + 1 where id = 1 and version = 1
      

2.4 普通修改

    @Update("<script> UPDATE sellout_warn_task SET execute_status = #{status},change_by =#{modifier} WHERE " +"operation_day =#{operationDay} AND sale_day=#{saleDay} AND lot_code=#{lotCode}</script>")int updateTaskExecuteStatus(@Param("saleDay") String saleDay, @Param("operationDay") String operationDay,@Param("lotCode") String lotCode, @Param("status") int status, @Param("modifier") String modifier);

2.5 批量修改

批量更新数据-多个字段都需要更新

    @Update("<script>" +"update sellout_warn_sku  " +"   <trim prefix='set' suffixOverrides=','> " +"       <trim prefix='status =case' suffix='end,'> " +"           <foreach collection='list' item='item' index='index'> " +"               <if test='item.status !=null'>      when id=#{item.id} then #{item.status} </if>   " +"           </foreach>    " +"       </trim>    " +"       <trim prefix='change_by =case' suffix='end,'>    " +"           <foreach collection='list' item='item' index='index'>     " +"               <if test='item.changeBy !=null'>      when id=#{item.id} then #{item.changeBy} </if> " +"          </foreach>    " +"       </trim>  " +"       <trim prefix='fail_reason =case' suffix='end,'>    " +"           <foreach collection='list' item='item' index='index'>     " +"               <if test='item.failReason !=null'>      when id=#{item.id} then #{item.failReason} </if> " +"          </foreach>    " +"       </trim>  " +"       <trim prefix='process_source =case' suffix='end,'>    " +"           <foreach collection='list' item='item' index='index'>     " +"               <if test='item.processSource !=null'>      when id=#{item.id} then #{item.processSource} </if> " +"          </foreach>    " +"       </trim>  " +"       <trim prefix='max_sale_num =case' suffix='end,'>    " +"           <foreach collection='list' item='item' index='index'>     " +"               <if test='item.maxSaleNum !=null'>      when id=#{item.id} then #{item.maxSaleNum} </if> " +"          </foreach>    " +"       </trim>  " +"   </trim>  " +"where id in  " +"   <foreach collection='list' index='key' item='item' separator=',' open='(' close=')'>    #{item.id}  " +"   </foreach>" +"</script>")int batchUpdateStatusAndReason(List<SellOutWarnSkuDO> sellOutWarnSkuDos);

批量更新数据,单个字段的更新

@Update("<script>" +"update sellout_warn_sku  " +"   <trim prefix='set' suffixOverrides=','> " +"       <trim prefix='base_predict_quantity =case' suffix='end,'> " +"           <foreach collection='list' item='item' index='index'> " +"               <if test='item.basePredictQuantity !=null'>      when id=#{item.id} then #{item.basePredictQuantity} </if>   " +"           </foreach>    " +"       </trim>    " +"       <trim prefix='or_predict_quantity =case' suffix='end,'>    " +"           <foreach collection='list' item='item' index='index'>     " +"               <if test='item.orPredictQuantity !=null'>      when id=#{item.id} then #{item.orPredictQuantity} </if> " +"          </foreach>    " +"       </trim>  " +"   </trim>  " +"where id in  " +"   <foreach collection='list' index='key' item='item' separator=',' open='(' close=')'>    #{item.id}  " +"   </foreach>" +"</script>")int batchUpdatePredicateValue(List<SellOutWarnSkuDO> sellOutWarnSkuDos);
@Update("<script>" +"update stc_block_sku  " +"   <trim prefix='set' suffixOverrides=','> " +"       <trim prefix='change_by =case' suffix='end,'> " +"           <foreach collection='list' item='item' index='index'> " +"               <if test='item.changeBy !=null'>      when id=#{item.id} then #{item.changeBy} </if>   " +"           </foreach>    " +"       </trim>    " +"       <trim prefix='utime =case' suffix='end,'>    " +"           <foreach collection='list' item='item' index='index'>     " +"               <if test='item.utime !=null'>      when id=#{item.id} then #{item.utime} </if> " +"          </foreach>    " +"       </trim>  " +"       <trim prefix='valid =case' suffix='end,'>    " +"           <foreach collection='list' item='item' index='index'>     " +"               <if test='item.valid !=null'>      when id=#{item.id} then #{item.valid} </if> " +"          </foreach>    " +"       </trim>  " +"   </trim>  " +"where id in  " +"   <foreach collection='list' index='key' item='item' separator=',' open='(' close=')'>    #{item.id}  " +"   </foreach>" +"</script>")int batchUpdateByPrimaryKeySelective(List<StcBlockSkuDO> batchDeleteBlockSkuDOList);

2.6 updateByPrimaryKeySelective

ReturnpalnTaskDO returnpalnTaskDO = new ReturnpalnTaskDO().setId(id).setStatus(8);  
repository.update(returnpalnTaskDO, ReturnpalnTaskDO.Column.status)public int update(ReturnpalnTaskDO returnpalnTaskDO, ReturnpalnTaskDO.Column... selective) {return mapper.updateByPrimaryKeySelective(qtyApplyDo, selective);}ModifyQtyBillDO modifyDO = new ModifyQtyBillDO().setId(billId).setStatus(APPROVE.code)                  .setModifyResultType(ModifyResultTypeEnum.MODIFY_BY_SUPPLIER_APPLY.code).setModifySuccessMaxSaleQty(model.getExpectMaxSaleQty()).setApproveSaleQty(lockQty);modifyQtyRepository.updateByModel(modifyDO, ModifyMaxSaleQtyApplyDO.Column.status,ModifyMaxSaleQtyApplyDO.Column.modifyResultType, ModifyMaxSaleQtyApplyDO.Column.modifySuccessMaxSaleQty,ModifyMaxSaleQtyApplyDO.Column.approveSaleQty);int updateByModel(ModifyQtyBillDO model, ModifyMaxSaleQtyApplyDO.Column... selective);public int updateByModel(ModifyQtyBillDO model, ModifyMaxSaleQtyApplyDO.Column... selective) {return mapper.updateByPrimaryKeySelective(model, selective);}

2.7 将ids们的某些字段值进行修改

    <update id="updateStatusById">update modify_max_sale_qty_applyset status = #{statusCode},modify_result_type =#{modifyResultTypeCode},approver =#{approver}where id in<foreach collection="ids" open="(" close=")" item="item" separator=",">#{item}</foreach></update>

三、查

前要:常见三种查询

  • 普通Repository查询 List query(model)

可以将经常查询的几个参数,封装成model,不同类型的查询,都可以通过这个model去查。

public class StcBlackSkuModel {/*** 网店集合*/private List<Long> netPoiIds;/*** 当前用户输入的skuId集合*/private List<Long> skuIdList;private Integer offset;private Integer limit;/*** 业务类型: {@link BlackSkuBusinessTypeEnum}*/private Integer businessType;
}

然后再构造Example的时,每个属性都判空下,非空才set criterria值。这样一个Repository查询接口就非常通用

  • 走master查询
  • 通过greaterThanId查询

3.0 强制走索引

SELECT  * 
FROM XXX_log force index(ctime) 
WHERE `ctime` BETWEEN '2017-09-11 09:34:13'  AND '2017-10-11 09:34:13'
ORDER BY  id DESC 
LIMIT 0, 30

3.1 普通查询

分页 + in

    @Select("<script>" +"select " +"id,operation_day,sale_day,warn_type,sku_id,net_poi_id,sku_price,sku_category_id,or_predict_quantity,max_sale_num,status " +"from " +"sellout_warn_sku " +"where " +"operation_day in " +"<foreach collection='operateDates' index = 'index' item = 'id' open= '(' separator=', ' close=')'>\n" +"#{id}" +"</foreach>" +"and " +"sale_day=#{saleDate} " +"and " +"net_poi_id in " +"<foreach collection='netPoiIds' index = 'index' item = 'id' open= '(' separator=', ' close=')'>\n" +"#{id}" +"</foreach>" +"and " +"sku_category_id=#{categoryId} "+"and " +" valid = 1 " +"limit " +"#{offset},#{rows}"+"</script>")@Results({@Result(column = "id", property = "id", jdbcType = JdbcType.BIGINT, id = true),@Result(column = "operation_day", jdbcType = JdbcType.VARCHAR, property = "operationDay"),@Result(column = "sale_day", jdbcType = JdbcType.VARCHAR, property = "saleDay"),@Result(column = "warn_type", jdbcType = JdbcType.INTEGER, property = "warnType"),@Result(column = "sku_id", jdbcType = JdbcType.BIGINT, property = "skuId"),@Result(column = "net_poi_id", jdbcType = JdbcType.BIGINT, property = "netPoiId"),@Result(column = "sku_price", jdbcType = JdbcType.BIGINT, property = "orPredictQuantity"),@Result(column = "sku_category_id", jdbcType = JdbcType.INTEGER, property = "skuCategoryId"),@Result(column = "or_predict_quantity", jdbcType = JdbcType.BIGINT, property = "orPredictQuantity"),@Result(column = "max_sale_num", jdbcType = JdbcType.BIGINT, property = "maxSaleNum"),@Result(column = "status", property = "status", jdbcType = JdbcType.INTEGER)})List<SellOutWarnSkuDO> sellOutWarnForProcurementWorkBench(@Param("operateDates") List<String> operateDates,@Param("saleDate") String saleDate,@Param("netPoiIds") List<Long> netPoiIds,@Param("categoryId") Long skuCategoryId,@Param("offset") Integer offset,@Param("rows") Integer rows);

也可以这样

两点

1、每个关键字或字段后面,空出来一格

2、需要@Result一一对应

@Result:https://blog.csdn.net/heartsdance/article/details/119734906

3、@Result中的jdbcType = JdbcType.INTEGER,可以省略. 并且表中字段和DO中字段相同的列,比如id、status、valid这种,可以不用@Result注解修饰

    @Results({@Result(column = "id", property = "id", jdbcType = JdbcType.BIGINT, id = true),@Result(column = "sale_day", jdbcType = JdbcType.VARCHAR, property = "saleDay"),@Result(column = "lot_code", jdbcType = JdbcType.VARCHAR, property = "lotCode"),@Result(column = "warn_type", jdbcType = JdbcType.INTEGER, property = "warnType"),@Result(column = "sku_id", jdbcType = JdbcType.BIGINT, property = "skuId"),@Result(column = "net_poi_id", jdbcType = JdbcType.BIGINT, property = "netPoiId"),@Result(column = "sku_supplier_id", jdbcType = JdbcType.BIGINT, property = "skuSupplierId"),@Result(column = "max_sale_num", jdbcType = JdbcType.BIGINT, property = "maxSaleNum"),@Result(column = "or_predict_quantity", jdbcType = JdbcType.BIGINT, property = "orPredictQuantity"),})

最普通

@Select("<script> SELECT DISTINCT sku_category FROM sellout_warn_category_count WHERE operation_day " +"=#{operationDay} and sale_day=#{saleDay} AND lot_code=#{lotCode} AND valid=1 </script>")List<Long> queryCategoriesBySaleDayAndOperationDayAndLotCode(@Param("saleDay") String saleDay,@Param("operationDay") String operationDay, @Param("lotCode") String lotCode);

子查询

 @Select({"<script>" +" select" +" a.pc_id as pc_id, a.material_sku_id as material_sku_id," +" a.material_rate as material_rate" +" from material_sku_loss a" +" where pc_id = #{pcId}" +" and material_sku_id in" +"<foreach collection='materialSkuIds' index = 'index' item = 'id' open= '(' separator=', ' close=')'>\n" +" #{id} " +"</foreach>" +" and process_date = (select max(process_date) from material_sku_loss where material_sku_id = a. material_sku_id)" +"</script>"})@Results({@Result(column = "pc_id", property = "pcId", jdbcType = JdbcType.BIGINT),@Result(column = "material_sku_id", property = "materialSkuId", jdbcType = JdbcType.BIGINT),@Result(column = "material_rate", property = "materialRate", jdbcType = JdbcType.DECIMAL)})List<MaterialSkuLossDO> getMaterialSkuLoss(Long pcId, List<Long> materialSkuIds);

in查询

 @Select("<script>" +"select sku_id from clear_inventory_recommend where poi_id=#{poiId} and version=#{version} and sku_id in " +"<foreach collection='skuIdList' index = 'index' item = 'id' open= '(' separator=', ' close=')'>\n" +"    #{id}\n" +"    </foreach>" +"</script>")List<Long> queryClearStockSkuIdList(Long poiId, List<Long> skuIdList, String version);@Select(("<script>" +"select sku_id from sku_operation_record where effective_date=#{effectiveDate} and status=#{status} and sku_id in " +"<foreach collection='skuIdList' index = 'index' item = 'id' open= '(' separator=', ' close=')'>\n" +"#{id}" +"</foreach>" +" and poi_id in " +"<foreach collection='poiIdList' index = 'index' item = 'id' open= '(' separator=', ' close=')'>\n" +"#{id}" +"</foreach>" +"</script>"))List<Long> querySkuIdList(String effectiveDate, List<Long> poiIdList, List<Long> skuIdList, Integer status);

!=

 @Select({"<script>","select distinct rdc_id from sku_stock_target_management","where schedule_date = #{scheduleDate} and  algo_status = #{algoSyncStatus} and sync_type != 3","</script>"})List<Long> querySyncRdcIdListByDate(Integer algoSyncStatus,String scheduleDate);

排序和limit

@Select("select result from job_run_result where job_name=#{jobName} and run_status=#{runStatus} order by id asc limit #{rows}")
List<String> getRecentlyResult(String jobName, Integer runStatus, Integer rows);或者
limit #{from},#{size}@Select({"<script>","select distinct rdc_id from sku_stock_target_management","where schedule_date between #{startDate} and #{endDate} and algo_status = #{algoSyncStatus} and sync_type != 3","</script>"})List<Long> querySyncRdcIdList(Integer algoSyncStatus,String startDate,String endDate);

left join

 @Select(value = "select r.id,r.name,r.description from user_role ur left join role r on ur.role_id=r.id and ur.user_id=#{userId}")List<Role> getRoleListByUserId(Integer uid);

3.2 查询的PO中字段含有text属性的数据时,选择selectByExampleWithBLOBs

List<RefundOutboundBillExtraFieldsPO> extraFieldsPOS = extraFieldsPOMapper.selectByExampleWithBLOBs(extraFieldsPOExample);

若检索大字段时,则需要使用selectByExampleWithBLOBs ,一般情况则使用selectByExample 即可。

注意:如果我们要在数据库中查询的结果集中,包含text类型的字段,一定要用selectByExampleWithBLOBs,否则会查不到对应字段的结果集。

3.3 深分页问题

推荐使用id,而非limit、offset

public List<SellOutWarnSkuDO> querySellOutWarnInfoIdGreaterThan(@NonNull String saleDate,@NonNull List<Long> netPoiIdList, @NonNull List<Long> secondCategoryIdList) {// 构建查询条件LocalDate operateLocalDateT1 = DateUtils.toLocalDate(saleDate, DateUtils.yyyyMMdd);String operateDateT0 = DateUtils.localDateToString(operateLocalDateT1.minusDays(1), DateTimeFormatter.ofPattern(DateUtils.yyyyMMdd));List<String> operateDates = Lists.newArrayList(operateDateT0, saleDate);boolean loop = true;long id = 0L;List<SellOutWarnSkuDO> resultDOList = Lists.newArrayList();try {do {SellOutWarnSkuDOExample example = new SellOutWarnSkuDOExample();example.limit(LionUtils.getBatchQuerySellOutWarnSize());example.setOrderByClause("id asc");SellOutWarnSkuDOExample.Criteria criteria = example.createCriteria();criteria.andOperationDayIn(operateDates);criteria.andSaleDayEqualTo(saleDate);criteria.andNetPoiIdIn(netPoiIdList);criteria.andSkuCategoryIdIn(secondCategoryIdList);criteria.andValidEqualTo(Boolean.TRUE);criteria.andIdGreaterThan(id);List<SellOutWarnSkuDO> selectByExample;selectByExample = sellOutWarnSkuUdfMapper.selectByExample(example);if (CollectionUtils.isNotEmpty(selectByExample)) {resultDOList.addAll(selectByExample);int size = selectByExample.size();if (size < LionUtils.getBatchQuerySellOutWarnSize()) {loop = false;} else {id = selectByExample.get(size - 1).getId();}} else {loop = false;}} while (loop);} catch (Exception e) {log.error("queryAllSellOutWarnSkuDOList Exception,saleDate:[{}],netPoiIdList:[{}], secondCategoryIdList:[{}] ",saleDate, GsonUtil.toJson(netPoiIdList), GsonUtil.toJson(secondCategoryIdList), e);}return resultDOList;}public List<OriginReturnSkuDO> getAllOriginReturnSkus(String packKey, String taskCode) {long id = 0L;List<OriginReturnSkuDO> result = Lists.newArrayList();List<OriginReturnSkuDO> selectByExample;boolean loop = true;taskCode = Objects.isNull(taskCode) ? StringUtils.EMPTY : taskCode;do {OriginReturnSkuDOExample example = new OriginReturnSkuDOExample();example.limit(BATCH_THRESHOLD);example.setOrderByClause("id asc");OriginReturnSkuDOExample.Criteria criteria = example.createCriteria();criteria.andPackKeyEqualTo(packKey);criteria.andValidEqualTo(Boolean.TRUE);criteria.andIdGreaterThan(id);criteria.andNeedPackEqualTo(Boolean.TRUE);criteria.andTaskCodeEqualTo(taskCode);selectByExample = originReturnSkuMapper.selectByExample(example);if (CollectionUtils.isNotEmpty(selectByExample)) {result.addAll(selectByExample);int size = selectByExample.size();if (size < BATCH_THRESHOLD) {loop = false;} else {id = selectByExample.get(size - 1).getId();}} else {loop = false;}} while (loop);log.info("getOriginReturnSkus,packKey:[{}],taskCode:[{}],result:[{}]", packKey, taskCode,GsonUtil.toJson(result));return result;}

底层执行的sql

selectid,sku_id,task_code
fromorigin_return_sku
WHERE(pack_key = 'a'and valid = trueand id > 0and need_pack = trueand task_code = 'b')
order byid asc
limit5;select * from sellout_warn_sku WHERE ( operation_day in ( '20220831' , '20220901' ) and sale_day = '20220901' and net_poi_id in (  ) and sku_category_id in ( ) and valid = true and id > 0 ) order by id asc limit 1000 ===============================================================================================selectid,sku_id,task_code
fromorigin_return_sku
WHERE(pack_key = 'a'and valid = trueand id > 13260这是根据id = selectByExample.get(size - 1).getId()计算出来的值and need_pack = trueand task_code = 'b')
order byid asc
limit5;

3.4 selectByExampleWithRowBounds:不是真正意义上的分页查询,底层并没有分野查询。会扫面全量数据

https://www.jianshu.com/p/f445e163b5ed

1、selectByExample

<if test="rows != null"><if test="offset != null">limit ${offset}, ${rows}</if><if test="offset == null">limit ${rows}</if>

方式0:

example.limit(offset, limit);

方式一:

前端传递offset和limit

首页0,50

下一页:50,50

这种形式,使用

example.setOffset(request.getPaging().getOffset());
example.setRows(request.getPaging().getLimit());

方式二:

        example.page()//第一页,page = 0public ReturnPlanOrderDOExample page(Integer page, Integer pageSize) {this.offset = page * pageSize;this.rows = pageSize;return this;}

3.5 走主库查

    private List<StcBlockSkuDO> queryStcBlockSkuByMaster(Long netPoiId, List<Long> skuIds) {//查询主库try {ZebraForceMasterHelper.forceMasterInLocalContext();return blockSkuRepository.queryBlockByMaster(netPoiId, skuIds);} catch (Exception e) {log.error("走主库查询黑名单sku,netPoiId:[{}], skuIds:[{}]", netPoiId, GsonUtils.toJsonString(skuIds), e);throw new BusinessException(RespCodeEnum.BIZ_ERROR.code, "走主库查询黑名单sku error");} finally {ZebraForceMasterHelper.clearLocalContext();}}

3.6 一个查询条件作为一个key形式去查询(防止过多的in条件,导致笛卡尔乘积),使用OR的形式

1、从MySQL 5.7.3开始,优化器能够将范围扫描访问方法应用于这种形式的查询:
SELECT ... FROM t1 WHERE ( col_1, col_2 ) IN (( 'a', 'b' ), ( 'c', 'd' ));2、以前,要使用范围扫描,需要将查询写为:
SELECT ... FROM t1 WHERE ( col_1 = 'a' AND col_2 = 'b' ) OR ( col_1 = 'c' AND col_2 = 'd' );3、为了优化器使用范围扫描,查询必须满足以下条件:
只有IN谓词可以使用,NOT IN 不行。
IN谓词左边的行构造函数中可能只有列引用。
IN谓词的右边必须有多个行构造函数。

手写sql

 @Results(id="predictSalesByRegionDTO",value={@Result(column="region_id", jdbcType= JdbcType.BIGINT, property="regionId"),@Result(column="region_name", jdbcType= JdbcType.BIGINT, property="regionName"),@Result(column="planning_date" ,jdbcType=JdbcType.VARCHAR, property="planningDate" ),@Result(column="predict_base_date" ,jdbcType= JdbcType.VARCHAR, property="predictBaseDate" ),@Result(column="role_type" ,jdbcType=JdbcType.BIGINT, property="roleType" ),@Result(column="planning_value" ,jdbcType=JdbcType.BIGINT, property="planningValue" ),@Result(column="rdc_id", jdbcType=JdbcType.BIGINT ,property="rdcId" )})@Select({"<script>","select  region_id, region_name, planning_date, predict_base_date, role_type, planning_value, rdc_id ","from plan_collaboration_data ","where planning_date = #{planningDate}","<choose>","<when test='regions != null and regions.size() &gt; 0'>"," and region_id in","<foreach collection='regions' item='region' open= '(' separator=', ' close=')'>","#{region}","</foreach>","</when>","<otherwise>","and region_id is not null","</otherwise>","</choose>","<if test='conditions != null and conditions.size() &gt; 0'>"," and ","<foreach collection='conditions' item='condition' open= '(' separator='or' close=')'>","<trim prefix='(' suffix=')'>","predict_base_date = #{condition.predictBaseDate} and role_type = #{condition.roleType}","</trim>","</foreach>","</if>","<when test='rdcIds != null and rdcIds.size() &gt; 0'>"," and rdc_id in ","<foreach collection='rdcIds' item='rdcId' open= '(' separator=', ' close=')'>","#{rdcId}","</foreach>","</when>","</script>"})List<PredictSalesByRdcDTO> queryDataByRegionRoleAndDate(String planningDate, List<Long> regions, List<Long> rdcIds,List<PredictBaseAndRoleCondition> conditions);

或者mybatis

example.or(新的criteria)

参考:

 @Results({@Result(column = "id", property = "id", id = true),@Result(column = "sale_day", property = "saleDay"),@Result(column = "net_poi_id", property = "netPoiId"),@Result(column = "sku_id", property = "skuId"),@Result(column = "max_sale_num_after", property = "maxSaleNumAfter"),@Result(column = "ctime", property = "ctime")})@Select("<script>" +"select " +"id, sale_day, net_poi_id, sku_id, max_sale_num_after, ctime " +"from " +"sdc_trusteeship_sku_operate_log " +"where " +"<if test='conditions != null and conditions.size() &gt; 0'>" +"<foreach collection='conditions' item='condition' open= '(' separator='or' close=')'>" +"<trim prefix='(' suffix=')'>" +"sale_day = #{condition.saleDate} and net_poi_id = #{condition.netPoiId} and sku_id = #{condition.skuId}" +"</trim>" +"</foreach>" +"</if>" +"</script>")List<SdcTrusteeshipSkuOperateLogDO> queryOperateLogMaxSaleAfter(@Param("conditions") List<SkuScheduleKey> conditions);

a,b,c,d in(不同的值)

SELECTorigin_id,receive_id,execute_type,business_type,origin_cw_id
FROMreturn_plan_order
WHERE(origin_id,receive_id,execute_type,business_type,origin_cw_id) in (SELECTorigin_id,receive_id,execute_type,business_type,origin_cw_idFROMreturn_plan_orderWHEREreturn_day = '20220809' --   AND origin_id = 10000915GROUP BYorigin_id,receive_id,execute_type,business_type,origin_cw_idHAVINGcount(*) > 1)and return_day = '20220809'

四、其它

4.1 example中criteria对同一个字段赋值不会覆盖前一个值。

结果是:同一个字段会有两个值,即 a = 1 and a =2

数据库中没数据

select 
poi_id,refund_bill_no,source,status,supplier_id,complete_picking_time,create_at
from refund_outbound_bill 
where valid = 0 and valid = 1;

相关文章:

CRUD-SQL

文章目录 前置insertSelective和upsertSelective使用姿势手写sql&#xff0c;有两种方式 一、增当导入的数据不存在时则进行添加&#xff0c;有则更新 1.1 唯一键&#xff0c;先查&#xff0c;后插1.2 批量插1.2.1 批次一200、批次二200、批次三200&#xff0c;有一条数据写入失…...

【C语言 | 数组】C语言数组详解(经典,超详细)

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…...

第三十三节——组合式API生命周期

一、基本使用 组合式api生命周期几乎和选项式一致。注意组合式api是从挂载阶段开始 <template><div></div> </template> <script setup> import {onBeforeMount, onMounted,onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, } from …...

【Linux】Alibaba Cloud Linux 3 安装 PHP8.1

一、系统安装 请参考 【Linux】Alibaba Cloud Linux 3 中第二硬盘、MySQL8.、MySQL7.、Redis、Nginx、Java 系统安装 二、安装源 rpm -ivh --nodeps https://rpms.remirepo.net/enterprise/remi-release-8.rpm sed -i s/PLATFORM_ID"platform:al8"/PLATFORM_ID&q…...

【容器化】Kubernetes(k8s)

文章目录 概述Docker 的管理痛点什么是 K8s云架构 & 云原生 架构核心组件K8s 的服务注册与发现组件调用流程部署单机版部署主从版本Operator来源拓展阅读 概述 Docker 虽好用&#xff0c;但面对强大的集群&#xff0c;成千上万的容器&#xff0c;突然感觉不香了。 这时候就…...

stm32 HSUSB

/ stm32f407xx.h #define USB_OTG_HS_PERIPH_BASE 0x40040000UL #define USB_OTG_HS ((USB_OTG_GlobalTypeDef *) USB_OTG_HS_PERIPH_BASE) // // 定义全局变量 USBD_HandleTypeDef hUsbDeviceHS;并默认全零初始化/* USB Device handle structure */ typedef struct _USB…...

C# String.Trim 方法

String.Trim()方法定义&#xff1a; 命名空间&#xff1a;System 程序集&#xff1a;System.Runtime.dll 返回结果&#xff1a;返回一个新字符串&#xff0c;它相当于从当前字符串中删除了一组指定字符的所有前导匹配项和尾随匹配项。 Trim方法有三个重载的方法&#xff0c;…...

<Linux>(极简关键、省时省力)《Linux操作系统原理分析之Linux 进程管理 4》(8)

《Linux操作系统原理分析之Linux 进程管理 4》&#xff08;8&#xff09; 4 Linux 进程管理4.4 Linux 进程的创建和撤销4.4.1 Linux 进程的族亲关系4.4.2 Linux 进程的创建4.4.3 Linux 进程创建的过程4.4.4 Linux 进程的执行4.4.5 Linux 进程的终止和撤销 4 Linux 进程管理 4.…...

RT-Thread STM32F407 PWM

为了展示PWM效果&#xff0c;这里用ADC来采集PWM输出通道的电平变化 第一步&#xff0c;进入RT-Thread Settings配置PWM驱动 第二步&#xff0c;进入board.h&#xff0c;打开PWM宏 第三步&#xff0c;进入STM32CubeMX&#xff0c;配置时钟及PWM 第四步&#xff0c;回到R…...

idea中把spring boot项目打成jar包

打jar包 打开项目&#xff0c;右击项目选中Open Module Settings进入project Structure 选中Artifacts&#xff0c;点击中间的加号&#xff08;Project Settings->Artifacts->JAR->From modules with dependencies &#xff09; 弹出Create JAR from Modules&#…...

levelDB之基础数据结构-Slice

Slice是levelDB中用于操作字符串的数据结构&#xff0c;以字节为单位。 定义与实现 namespace leveldb {class LEVELDB_EXPORT Slice {public:// Create an empty slice.Slice() : data_(""), size_(0) {}// Create a slice that refers to d[0,n-1].Slice(const c…...

上位机模块之通用重写相机类

在常用的视觉上位机中&#xff0c;我们通常会使用单个上位机匹配多个相机或者多品牌相机&#xff0c;所以在此记录一个可重写的通用相机类&#xff0c;用于后续长期维护开发。 先上代码。 using HalconDotNet; using System.Collections.Generic;namespace WeldingInspection.M…...

机器人导航+OPENCV透视变换示例代码

透视变换又称四点变换&#xff0c;所以不能用于5边形这样的图形变换&#xff0c;不是真正的透视变换&#xff0c;但是这个方法可以把机器人看到的图像转换为俯视图&#xff0c;这样就可以建立地图&#xff0c;要不然怎么建立地图呢。 void CrelaxMyFriendDlg::OnBnClickedOk()…...

KofamScan-KEGG官方推荐的使用系同源和隐马尔可夫模型进行KO注释

文章目录 简介安装使用输入蛋白序列输出detail-tsv格式输出detail格式输出mapper格式 输出结果detail和detail-tsv格式mapper格式常用命令tmp目录 与emapper结果比较其他参数参考 简介 KofamScan 是一款基于 KEGG 直系同源和隐马尔可夫模型&#xff08;HMM&#xff09;的基因功…...

代码随想录算法训练营第五十五天丨 动态规划part16

583. 两个字符串的删除操作 思路 #动态规划一 本题和动态规划&#xff1a;115.不同的子序列 (opens new window)相比&#xff0c;其实就是两个字符串都可以删除了&#xff0c;情况虽说复杂一些&#xff0c;但整体思路是不变的。 这次是两个字符串可以相互删了&#xff0c;这…...

【Linux】kernel与应用消息队列的一种设计

Linux进程间通讯的方式有很多种&#xff0c;这里介绍一种通过消息队列的方式来实现kernel与APP之间的消息收发实现方式&#xff0c;这种方式特别适用于&#xff0c;kernel中发送消息&#xff0c;应用层收取消息。 消息队列设备驱动 该方法的设计思路即是创建一个消息队列的设…...

我们常说的网络资产,具体是如何定义的?

文章目录 什么叫网络资产&#xff1f;官方定义的网络资产网络资产数字化定义推荐阅读 什么叫网络资产&#xff1f; 通过百度查询搜索什么叫网络资产&#xff1f;大体上都将网络资产归类为计算机网络中的各类设备。 基本上会定义网络传输通信架构中用到的主机、网络设备、防火…...

WPF中可冻结对象

在WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;"可冻结对象"指的是那些在创建之后可以被设置为不可更改状态的对象。这种特性允许这些对象更有效地被共享和复制&#xff0c;并且可以增加性能。 例如&#xff0c;Brushes&#xff0c;P…...

【人工智能实验】A*算法求解8数码问题 golang

人工智能经典问题八数码求解 实际上是将求解转为寻找最优节点的问题&#xff0c;算法流程如下&#xff1a; 求非0元素的逆序数的和&#xff0c;判断是否有解将开始状态放到节点集&#xff0c;并设置访问标识位为true从节点集中取出h(x)g(x)最小的节点判断取出的节点的状态是不…...

Kafka学习笔记(二)

目录 第3章 Kafka架构深入3.3 Kafka消费者3.3.1 消费方式3.3.2 分区分配策略3.3.3 offset的维护 3.4 Kafka高效读写数据3.5 Zookeeper在Kafka中的作用3.6 Kafka事务3.6.1 Producer事务3.6.2 Consumer事务&#xff08;精准一次性消费&#xff09; 第4章 Kafka API4.1 Producer A…...

Typora for Mac:打造全新文本编辑体验

Typora for Mac是一款与众不同的文本编辑器&#xff0c;它不仅拥有直观易用的界面&#xff0c;还融合了Markdown语法和富文本编辑的功能&#xff0c;为用户带来了前所未有的写作和编辑体验。 一、简洁明了的界面设计 Typora for Mac的界面简洁明了&#xff0c;让用户可以专注…...

TikTok与媒体素养:如何辨别虚假信息?

在当今数字时代&#xff0c;社交媒体平台如TikTok已经成为信息传播和社交互动的主要渠道之一。然而&#xff0c;随之而来的是虚假信息的泛滥&#xff0c;这对用户的媒体素养提出了严峻的挑战。本文将探讨TikTok平台上虚假信息的现象&#xff0c;以及如何提高媒体素养&#xff0…...

Spring Boot 中使用 ResourceLoader 加载资源的完整示例

ResourceLoader 是 Spring 框架中用于加载资源的接口。它定义了一系列用于获取资源的方法&#xff0c;可以处理各种资源&#xff0c;包括类路径资源、文件系统资源、URL 资源等。 以下是 ResourceLoader 接口的主要方法&#xff1a; Resource getResource(String location)&am…...

1688往微信小程序自营商城铺货商品采集API接口

一、背景介绍 随着移动互联网的快速发展&#xff0c;微信小程序作为一种新型的电商形态&#xff0c;正逐渐成为广大商家拓展销售渠道、提升品牌影响力的重要平台。然而&#xff0c;对于许多传统企业而言&#xff0c;如何将商品信息快速、准确地铺货到微信小程序自营商城是一个…...

QStatusBar开发详解

一、QStatusBar接口说明 QStatusBar 类是 Qt 中用于创建和管理状态栏的类。它继承自 QFrame 类&#xff0c;提供了在主窗口底部显示消息、进度等信息的功能。以下是一些 QStatusBar 类的重要接口&#xff1a; 1.1 QStatusBar构造函数 QStatusBar(QWidget *parent nullptr);…...

后端接口性能优化分析-程序结构优化

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码&#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44d;三连支持&…...

【SpringBoot3+Vue3】三【实战篇】-后端(优化)

目录 一、登录优化-redis 1、SpringBoot集成redis 1.1 pom 1.2 yml 1.3 测试程序&#xff08;非必须&#xff09; 1.4 启动redis&#xff0c;执行测试程序 2、令牌主动失效&#xff08;代码优化&#xff09; 2.1 UserController设置token到redis 2.2 登录拦截器Log…...

DevExpress中文教程 - 如何在macOS和Linux (CTP)上创建、修改报表(上)

DevExpress Reporting是.NET Framework下功能完善的报表平台&#xff0c;它附带了易于使用的Visual Studio报表设计器和丰富的报表控件集&#xff0c;包括数据透视表、图表&#xff0c;因此您可以构建无与伦比、信息清晰的报表。 DevExpress Reports — 跨平台报表组件&#x…...

一个iOS tableView 滚动标题联动效果的实现

效果图 情景 tableview 是从屏幕顶部开始的&#xff0c;现在有导航栏&#xff0c;和栏目标题视图将tableView的顶部覆盖了 分析 我们为了达到滚动到某个分区选中标题的效果&#xff0c;就得知道 展示最顶部的cell或者区头在哪个分区范围内 所以我们必须首先获取顶部的位置 …...

代码执行相关函数以及简单例题

代码/命令 执行系列 相关函数 &#xff08;代码注入&#xff09;...

大数据爬虫分析基于Python+Django旅游大数据分析系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 基于Python和Django的旅游大数据分析系统是一种使用Python编程语言和Django框架开发的系统&#xff0c;用于处理和分…...

C# 结构体介绍

文章目录 定义结构体实例化结构体结构体的值类型特性结构体和类的区别限制 C# 中的结构体&#xff08;Struct&#xff09;是一种值类型数据结构&#xff0c;用于封装不同或相同类型的数据成一个单一的实体。结构体非常适合用来表示轻量级的对象&#xff0c;比如坐标点、颜色值或…...

【机器学习】特征工程:特征预处理,归一化、标准化、处理缺失值

特征预处理采用的是特定的统计方法&#xff08;数学方法&#xff09;将数据转化为算法要求的数字 1. 数值型数据 归一化&#xff0c;将原始数据变换到[0,1]之间 标准化&#xff0c;数据转化到均值为0&#xff0c;方差为1的范围内 缺失值&#xff0c;缺失值处理成均值、中…...

Pytorch torch.norm函数详解用法

torch.norm参数定义 torch版本1.6 def norm(input, p"fro", dimNone, keepdimFalse, outNone, dtypeNone)input input (Tensor): the input tensor 输入为tensorp p (int, float, inf, -inf, fro, nuc, optional): the order of norm. Default: froThe following …...

【DevOps】Git 图文详解(二):Git 安装及配置

Git 图文详解&#xff08;二&#xff09;&#xff1a;Git 安装及配置 1.Git 的配置文件2.配置 - 初始化用户3.配置 - 忽略.gitignore Git 官网&#xff1a;https://www.git-scm.com/ 下载安装包进行安装。Git 的使用有两种方式&#xff1a; 命令行&#xff1a;Git 的命令通过系…...

亚马逊美国站CPC认证ASTM F963测试项目要求有哪些?

ASTM F963是美国材料和试验联合会&#xff08;ASTM&#xff09;制定的儿童玩具安全性的标准规范&#xff0c;专门针对儿童玩具产品的安全性进行了规定和要求。 ASTM F963标准的内容和要求包括&#xff1a; 1、物理机械性能&#xff1a;规定了玩具的物理机械性能要求&#xff0…...

通付盾Web3专题 | KYT/AML:Web3合规展业的必要条件

与传统证券一样&#xff0c;基于区块链技术发展出来的虚拟资产交易所经历了快速发展而缺乏有效监管的行业早期。除了科技光环加持的各种区块链项目方、造富神话之外&#xff0c;交易所遭到黑客攻击、内部偷窃作恶、甚至经营主体异常而致使投资人血本无归的案例亦令人触目惊心。…...

Centos8配置Zabbix5.0中文汉化

1.点击【Sign in】按钮&#xff0c;输入用户名和密码进入Zabbix的首页&#xff0c;结果如图。 2.点击左边导航栏的【User settings】链接&#xff0c;进入用户个性化设置界面&#xff0c;结果如图。 3.在搭建Zabbix的虚拟机上使用yum命令下载中文包。 yum install glibc-langpa…...

元数据管理,数字化时代企业的基础建设

随着新一代信息化、数字化技术的应用&#xff0c;众多领域通过科技革命和产业革命实现了深度化的数字改造&#xff0c;进入到以数据为核心驱动力的&#xff0c;全新的数据处理时代&#xff0c;并通过业务系统、商业智能BI等数字化技术和应用实现了数据价值&#xff0c;从数字经…...

大数据之Hive:regexp_extract函数案例

目录 一、正则的通配符简介1、正则表达式的符号及意义2、各种操作符的运算优先级&#xff1a; 二、案例数据要求分析实现输出结果实现2实现3 总结 一、正则的通配符简介 1、正则表达式的符号及意义 符号含义实列/做为转意&#xff0c;即通常在"/"后面的字符不按原来…...

tsconfig.json无法写入文件“XXXX“因为它会覆盖输入文件

在开发ts项目的时候&#xff0c;包错提示无法写入文件&#xff1a; tsconfig.json无法写入文件"XXXX"因为它会覆盖输入文件 这是tsconfig.json文件配置问题&#xff0c;需要加入下面的配置就好了&#xff1a; {"compilerOptions": {"outDir": …...

本周Github有趣项目:draw-a-ui等

有趣的项目、工具和库 gpt-crawler 抓取网站以生成知识文件&#xff0c;从而从 URL 创建您自己的自定义 GPT。 需要步骤&#xff1a; 配置运行爬虫、 将您的数据上传到 OpenAI&#xff1a;使用此选项通过 UI 访问您生成的知识&#xff0c;您可以轻松与他人共享 创建自定义助…...

VBA如何快速识别Excel单元格中的文本数字

Excel中一种非常特殊的数字&#xff0c;这些数字看似数字&#xff0c;其实是文本格式&#xff08;下文简称为文本数字&#xff09;&#xff0c;在单元格的左上角会有一个绿色小三角作为标志&#xff0c;如B1:B3单元格。 在编程时为什么需要区分普通数字和文本数字呢&#xff…...

Mysql数据库 16.SQL语言 数据库事务

一、数据库事务 数据库事务介绍——要么全部成功要么全部失败 我们把完成特定的业务的多个数据库DML操作步骤称之为一个事务 事务——就是完成同一个业务的多个DML操作 例&#xff1a; 数据库事务四大特性 原子性&#xff08;A&#xff09;&#xff1a;一个事务中的多个D…...

docker 部署Redis集群(三主三从,以及扩容、缩容)

1&#xff1a;创建6个redis容器 docker run -d --name redis01 --net host --privilegedtrue -v /opt/redis/redis01:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381 docker run -d --name redis02 --net host --privilegedtrue -v /opt/redis/redis0…...

JavaScript 浮点数运算的精度问题及解决

JavaScript 浮点数运算的精度问题及解决 在 JavaScript 中整数和浮点数都属于 Number 数据类型&#xff0c;当浮点数做数学运算的时候&#xff0c;你经常会发现一些问题&#xff0c;举几个例子&#xff1a; 0.1 0.2 0.30000000000000004 console.log(0.1 0.2) 0.3000000…...

基于STM32的无线传感器网络(WSN)通信方案设计与实现

无线传感器网络&#xff08;Wireless Sensor Network&#xff0c;简称WSN&#xff09;是由一组分布式的无线传感器节点组成的网络&#xff0c;用于监测和收集环境中的各类物理信息。本文将基于STM32微控制器&#xff0c;设计并实现一个简单的无线传感器网络通信方案&#xff0c…...

Flink和Kafka连接时的精确一次保证

Flink写入Kafka两阶段提交 端到端的 exactly-once&#xff08;精准一次&#xff09; kafka -> Flink -> kafka 1&#xff09;输入端 输入数据源端的 Kafka 可以对数据进行持久化保存&#xff0c;并可以重置偏移量&#xff08;offset&#xff09; 2&#xff09;Flink内…...

UE4动作游戏实例RPG Action解析三:实现效果,三连击Combo,射线检测,显示血条,火球术

一、三连Combo 实现武器三连击,要求: 1.下一段Combo可以随机选择, 2.在一定的时机才能再次检测输入 3. 等当前片段播放完才播放下一片段 1.1、蒙太奇设置 通过右键-新建蒙太奇片段,在蒙太奇里创建三个片段,并且移除相关连接,这样默认只会播放第一个片段 不同片段播…...

Linux/麒麟系统上部署Vue+SpringBoot前后端分离项目

目录 1. 前端准备工作 1.1 在项目根目录创建两份环境配置文件 1.2 环境配置 2. 后端准备工作 2.1 在项目resources目录创建两份环境配置文件 2.2 环境配置 3. 前后端打包 3.1 前端打包 3.2 后端打包 4、服务器前后端配置及部署 4.1 下载、安装、启动Nginx 4.2 前端项目部署…...