技术点随记

java8

单个list 找出重复元素

    public static <E> List<E> getDuplicateElements(List<E> list) {
        return list.stream()                              // list 对应的 Stream
                   .collect(Collectors.toMap(e -> e, e -> 1, Integer::sum)) // 获得元素出现频率的 Map,键为元素,值为元素出现的次数
                   .entrySet()
                   .stream()                              // 所有 entry 对应的 Stream
                   .filter(e -> e.getValue() > 1)         // 过滤出元素出现次数大于 1 (重复元素)的 entry
                   .map(Map.Entry::getKey)                // 获得 entry 的键(重复元素)对应的 Stream
                   .collect(Collectors.toList());         // 转化为 List
    }

参考:https://segmentfault.com/q/1010000008051168

分组后对元素继续处理(加和、排序等)

Map<String, TInsHiddenDangerMeasure> rectifyMeasureMap = rectifyMeasures.stream().collect(
                    Collectors.groupingBy(TInsHiddenDangerMeasure::getHiddenDangerReportId,
							//分组后根据getUploadTime排序并取第一个元素
                            Collectors.collectingAndThen(Collectors.reducing((h1, h2) -> h1.getUploadTime().isAfter(h2.getUploadTime()) ? h1 : h2), Optional::get)));

处理 Non-terminating decimal expansion; no exact representable decimal result. 异常

该错误由无限小数导致的,处理如下:进行除法时设置保留小数位及进数方式

        long s = 3L;
        long x = 7L;
        BigDecimal b = new BigDecimal(s);
        BigDecimal d = new BigDecimal(x);
        BigDecimal l = b.divide(d, 4, BigDecimal.ROUND_HALF_UP);
        System.out.println(l);

ORACLE

DECIMAL和NUMBER

建表语句中decimal类型就是number类型,建表后类型就变成了number,方便建表脚本在其他类型的数据库中执行。

字段值长度注意

数据默认以字节存入,3个字节为一个中文字符

表名、字段名长度限制

所谓标识符,是用户自定义的关键词,比如表名、字段名、视图名、序列名、主键等,因此,数据库表名、字段名也属于标识符。标识符最大长度30字符。

varchar2限制

varchar2最大能存4000字节内容,超过的大字符内容使用clob类型。

查询关键字in 个数限制

限制在1000个以内,否则会报错

WHERE (TASK_NO IN (?,?……省略……?,?) AND FLOW_KEY IN (?,?,?) AND STATUS = ?)
### Cause: java.sql.SQLSyntaxErrorException: ORA-01795: 列表中的最大表达式数为 1000

拼接查询字段

||进行拼接,如:

 SELECT l.TASK_NO,l.CURRENT_USER_NAME||'('||l.CURRENT_USER_ID ||')' CURRENT_USER_NAME FROM FLOW_LOG l ;

连表修改数据

UPDATE
        DANGER_REPORT h
SET
        h.AREA_CODE = (
        SELECT
                tsdp.PER_CODE
        FROM
                PERMISSION tsdp
        WHERE
                tsdp.PER_CODE = SUBSTR(h.CHECK_INDUSTRIAL_ZONE_CODE, 0, 8)),
        h.AREA_NAME = (
        SELECT
                tsdp.PER_NAME
        FROM
                PERMISSION tsdp
        WHERE
                tsdp.PER_CODE = SUBSTR(h.CHECK_INDUSTRIAL_ZONE_CODE, 0, 8))
WHERE
        h.AREA_CODE IS NULL
        AND h.CHECK_INDUSTRIAL_ZONE_CODE IS NOT NULL AND h.TASK_NO IS NOT NULL AND h.STATUS = '1'
;

oracle分页查询的坑

工作过程中碰到的一个坑:五百多条数据创建时间相同,根据创建时间排序之后导致某几页的数据相同,要么再加上一个数据不同的字段作为排序,要么不按创建时间排序。可参考:在Oracle数据库中查询数据时,不同分页出现数据重复的问题

拆分字段内容

参考:https://blog.csdn.net/weixin_46636220/article/details/129665978
拆分的字段应该加索引

SELECT
    id,
    substr(
        column_name,
        instr( column_name, ',', 1, levels.lvl ) + 1,
        instr( column_name, ',', 1, levels.lvl + 1 ) - ( instr( column_name, ',', 1, levels.lvl ) + 1 ) 
    ) AS column_name 
FROM
    (
    SELECT
        id,
        ',' || column_name || ',' AS column_name,
        length( column_name ) - nvl( length( REPLACE ( column_name, ',' ) ), 0 ) + 1 AS cnt 
    FROM
        table_name 
    ) a,
    (
    SELECT ROWNUM AS
        lvl 
    FROM
        (
        SELECT
            MAX( length( column_name || ',' ) - nvl( length( REPLACE ( column_name, ',' ) ), 0 ) ) max_len 
        FROM
            table_name 
        ) CONNECT BY LEVEL <= max_len 
    ) levels 
WHERE
    levels.lvl <= a.cnt 
ORDER BY
    id

Mybatis

Mybatis连子表查询分页问题

会按连表查询后的数据来进行分页,解决方式:

  • 先查主表,再用mybatis的子查询,参考 https://mybatis.org/mybatis-3/sqlmap-xml.html#nested-select-for-collection
<resultMap id="blogResult" type="Blog">
  <collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>
</resultMap>

<select id="selectBlog" resultMap="blogResult">
  SELECT * FROM BLOG WHERE ID = #{id}
</select>

<select id="selectPostsForBlog" resultType="Post">
  SELECT * FROM POST WHERE BLOG_ID = #{id}
</select>

Mybatis-plus自动填充

mybatisplus官方文档里其实已经写得很清楚了。需要注意的是handler中所有填充字段的类型需要和setFieldValByName方法中设置值的类型一致,否则会报错。

import lombok.Data;
@Data
@TableName("")
public class DataPojo implements MetaObjectHandler {
    @ApiModelProperty("创建人")
    @TableField(value = "CREATE_BY", fill = FieldFill.INSERT)
    private String createBy;

    @ApiModelProperty("创建时间")
    @TableField(value = "CREATE_TIME", fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    @ApiModelProperty("更新人")
    @TableField(value = "UPDATE_BY", fill = FieldFill.UPDATE)
    private String updateBy;

    @ApiModelProperty("更新时间")
    @TableField(value = "UPDATE_TIME", fill = FieldFill.UPDATE)
    private LocalDateTime updateTime;
}
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createBy", "", metaObject);
        this.setFieldValByName("createTime", LocalDateTime.now(), metaObject);
        this.updateFill(metaObject);
    }
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updatePerson", "", metaObject);
        this.setFieldValByName("updateDateTime", LocalDateTime.now(), metaObject);
    }
}

spring家族

@Transactional失效场景

@Transactional 加于private方法, 无效
@Transactional 加于未加入接口的public方法, 再通过普通接口方法调用, 无效
@Transactional 加于接口方法, 无论下面调用的是privatepublic方法, 都有效
**@Transactional 加于接口方法后, 被本类普通接口方法直接调用, 无效**
@Transactional 加于接口方法后, 被本类普通接口方法通过接口调用, 有效
@Transactional 加于接口方法后, 被它类的接口方法调用, 有效
@Transactional 加于接口方法后, 被它类的私有方法调用后, 有效

参考:https://blog.csdn.net/w1028556865/article/details/125085130

业务幂等性处理

  • 场景:用户浏览器用两个页签打开同一单据,可对同一数据重复编辑,要求某种状态后不可编辑或不可回到上一个状态。
  • 处理方式:前端传给后端的数据实时性已滞后,通过前端传过来的id去数据库中查询,校验编辑的状态来判断是否可继续编辑。

Freemarker

渲染数据特殊字符处理

报错:

对实体 "E" 的引用必须以 ';' 分隔符结尾。

加上 ![CDATA[ ${data} ]]

 <w:r>
    <w:rPr>
        <w:rFonts w:hint="eastAsia" w:ascii="微软雅黑" w:hAnsi="微软雅黑" w:eastAsia="微软雅黑" w:cs="微软雅黑"/>
        <w:color w:val="0A0A0A"/>
        <w:sz w:val="20"/>
        <w:szCs w:val="20"/>
        <w:lang w:val="en-US" w:eastAsia="zh-CN"/>
    </w:rPr>
    <w:t>![CDATA[ ${s.no} ]]</w:t>
</w:r>

Hutool

给图片加多行水印

		//获取模板图片
        ClassPathResource classPathResource = new ClassPathResource("pic/templatePic.png");
        InputStream blackPngIns = classPathResource.getInputStream();
        Image read = ImgUtil.read(blackPngIns);
        Img srcImg = Img.from(read);
        //不从中心点开始写
        srcImg.setPositionBaseCentre(false);
        Instant pressTextNow = Instant.now();
        srcImg.pressText("你好", new Color(242, 231, 174), new Font("黑体", Font.BOLD, 80), 1000, 1100, 1.0f);
        srcImg.pressText("我好", new Color(242, 231, 174), new Font("黑体", Font.BOLD, 80), 1000, 1300, 1.0f);
        srcImg.pressText("大家好", new Color(242, 231, 174), new Font("黑体", Font.BOLD, 80), 1000, 1500, 1.0f);
        srcImg.pressText(reasonFirstLine, new Color(242, 231, 174), new Font("黑体", Font.BOLD, 80), 1000, 1700, 1.0f);
        if (reason.length() > 30) {
            srcImg.pressText(reasonSecondLine, new Color(242, 231, 174), new Font("黑体", Font.BOLD, 80), 1340, 1800, 1.0f);
        }
        srcImg.setQuality(0.5);//压缩图片
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        //输出水印图片
        srcImg.write(os);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值