编程小技能 - wtdig/study GitHub Wiki

一、知识点

1、try-sources

注意:它要求在 try-with-resources 声明中定义的变量实现了 AutoCloseable 接口

JDK1.7开始,java引入了 try-with-resources 声明,将 try-catch-finally 简化为 try-catch,这其实是一种语法糖,在编译时会进行转化为 try-catch-finally 语句。新的声明包含三部分:try-with-resources 声明、try 块、catch 块。它要求在 try-with-resources 声明中定义的变量实现了 AutoCloseable 接口,这样在系统可以自动调用它们的close方法,从而替代了finally中关闭资源的功能。
但是,它们的异常抛出机制发生了变化。在过去的 try-catch-finally 结构中,我们在finally块中关闭资源通常是这样的:
    catch (Exception e) {
        e.printStackTrace(); // 第一处异常处理
    }
    finally {
        try {
            if (c != null) {
                c.close();
            }
        } catch (IOException e) {
            e.printStackTrace(); // 第二处异常处理
        }
    }

异常处理有两种情况:

try 块没有发生异常时,直接调用finally块,如果 close 发生异常,就处理。 try 块发生异常,catch 块捕捉,进行第一处异常处理,然后调用 finally 块,如果 close 发生异常,就进行第二处异常处理。 但是在 try-with-resources 结构中,异常处理也有两种情况(注意,不论 try 中是否有异常,都会首先自动执行 close 方法,然后才判断是否进入 catch 块,建议阅读后面的反编译代码):

try 块没有发生异常时,自动调用 close 方法,如果发生异常,catch 块捕捉并处理异常。 try 块发生异常,然后自动调用 close 方法,如果 close 也发生异常,catch 块只会捕捉 try 块抛出的异常,close 方法的异常会在catch 中被压制,但是你可以在catch块中,用 Throwable.getSuppressed 方法来获取到压制异常的数组。

public class Main {

    public static void startTest() {
        try (MyAutoCloseA a = new MyAutoCloseA();
             MyAutoCloseB b = new MyAutoCloseB()) {
            a.test();
            b.test();
        } catch (Exception e) {
            System.out.println("Main: exception");
            System.out.println(e.getMessage());
            Throwable[] suppressed = e.getSuppressed();
            for (int i = 0; i < suppressed.length; i++)
                System.out.println(suppressed[i].getMessage());
        }
    }

    public static void main(String[] args) throws Exception {
        startTest();
    }
}

2、代码重构

将临时变量抽取出来,采用查询的方式,比如:
int i = a*b;

先确定临时变量只赋值一次,finnal int i = a*b;

然后抽取出函数

finnal int i = queryCount();

private int queryCount(){
  return a*b;
}
2018.12.23  自封装字段、以对象取代数据值、将值对象改为引用对象

3、常用sql

json_extract(字段名称,'$.mappingSetId') mappingSetId存储在json中的名称
json_extract(detail.mapping_value,'$.mappingSetId')

find_in_set(传入值,字段名称)
find_in_set(#{targetField,jdbcType=VARCHAR}, a.target_field)

update 
sac_accounting_line_rules a 
left join sac_accounting_line_field_rules b 
on a.id = b.acct_line_rule_id 
set a.gmt_modified = NOW()
where a.is_deleted = 'n' and b.is_deleted = 'n' 
and b.target_field = "je_created_by"
and substring_index(a.bt,"_",1) = "intercompany"

substring_index(a.bt,"_",1) 截取指定字段,比如a.bt=aaa_vvv_11,结果为aaa

is not null 不包括空字符串

判断空字段串,使用 rule_condition ="" 或者 rule_condition <>"" ,如果该字段有多个空格也是可以的

update sac_accounting_line_rules a,sac_accounting_rules b set a.bt=b.bt  where a.acct_rule_id = b.id and b.bt like 'ot_ee%' and a.bt <> b.bt

 在MySQL数据库中,如果在insert语句后面带上ON DUPLICATE KEY UPDATE 子句,而要插入的行与表中现有记录的惟一索引或主键中产生重复值,那么就会发生旧行的更新;如果插入的行数据与现有表中记录的唯一索引或者主键不重复,则执行新纪录插入操作。

举例:
insert into daily_hit_counter (day, slot, cnt) values ('2017-11-19', 1, 1) ON DUPLICATE KEY UPDATE cnt = cnt + 1;


3表关联查询

<resultMap id="accountingRulesMap" type="sac.dal.vo.SacAccountingRulesTableVo">
        <id column="rules_id" property="id" jdbcType="BIGINT"/>
        <result column="rule_name" property="ruleName" jdbcType="VARCHAR"/>
        <result column="bt" property="bt" jdbcType="VARCHAR"/>
        <result column="creator" property="creator" jdbcType="VARCHAR"/>
        <result column="coa_id" property="coaId" jdbcType="BIGINT"/>
        <result column="rule_type" property="ruleType" jdbcType="VARCHAR"/>
        <result column="rule_condition" property="ruleCondition" jdbcType="VARCHAR"/>
        <result column="rule_condition_desc" property="ruleConditionDesc" jdbcType="VARCHAR"/>
        <result column="rule_condition_type" property="ruleConditionType" jdbcType="VARCHAR"/>
        <result column="approval_status" property="approvalStatus" jdbcType="VARCHAR"/>
        <result column="approver" property="approver" jdbcType="VARCHAR"/>
        <result column="approval_history" property="approvalHistory" jdbcType="VARCHAR"/>
        <collection property="accountingLineRules" ofType="sac.dal.vo.SacAccountingLineRulesVo">
            <id column="line_rules_id" property="lineRuleId" jdbcType="BIGINT"/>
            <result column="line_rule_name" property="lineRuleName" jdbcType="VARCHAR"/>
            <result column="collect_key" property="collectKey" jdbcType="VARCHAR"/>
            <collection property="lineFieldRules" ofType="sac.dal.vo.SacAccountingLineFieldRulesVo">
                <id column="line_field_id" property="lineFieldRulesId" jdbcType="BIGINT"/>
                <result column="target_field" property="targetField" jdbcType="VARCHAR"/>
                <result column="mapping_type" property="mappingType" jdbcType="VARCHAR"/>
                <result column="mapping_value" property="mappingValue" jdbcType="VARCHAR"/>
            </collection>
        </collection>
    </resultMap>
    <!--根据条件查询规则-->
     <select id="queryAccountingRulesByCond" resultMap="accountingRulesMap">
        select
        t.id rules_id,t.creator,t.bt,t.rule_name,t.coa_id,t.rule_condition_desc,
        t.rule_type,t.rule_condition,t.rule_condition_type,t.approval_status,
        t.approver,t.approval_history,m.id line_rules_id,m.collect_key,
        m.line_rule_name,n.id line_field_id,n.target_field,
        n.mapping_type,n.mapping_value
        from
        (select a.id,a.gmt_modified,a.creator,a.bt,a.rule_name,a.coa_id,
        a.rule_type,a.rule_condition_type,a.approval_status,a.rule_condition_desc,
        a.approver,a.approval_history,a.rule_condition
        <include refid="accountingRulesCommonCode"/>
        order by a.id desc
        <if test="cond.begin != null and cond.pageSize != null">
            limit #{cond.begin,jdbcType=BIGINT}, #{cond.pageSize,jdbcType=BIGINT}
        </if>) t
        left join
        (select b.* from sac_accounting_line_rules b where b.is_deleted = 'n') m
        on t.id = m.acct_rule_id
        left join
        (select c.* from sac_accounting_line_field_rules c where c.is_deleted = 'n') n
        on m.id = n.acct_line_rule_id
        order by t.gmt_modified desc,t.id desc,t.coa_id asc,m.id desc
    </select>

取多个list里面值的交集
List<List<String>> newStandard = new ArrayList<>();
Optional<List<String>> reduce = newStandard.parallelStream().reduce((a, b) -> {
                        a.retainAll(b);
                        return a;
                    });
                    // 取交集后的字段
                    List<String> finalField = reduce.orElse(new ArrayList<>());

4、编程习惯

1)对于可以出现报错的地方,都用日志记录。

Logger logger = LoggerFactory.getLogger(SacExcelJournalSourcesAoImpl.class);
logger.error("", e);

打印的日志,对应SacExcelJournalSourcesAoImpl路径

Logger logger = LoggerFactory.getLogger(""); 自定义名称,需要与日志配置文件相对应

比如:
Logger logger = LoggerFactory.getLogger("bus_event");
打印指定的名称:bus_event

日志配置文件,相对应的name=bus_event

<logger name="bus_event" level="DEBUG" additivity="false">
		<appender-ref ref="BUS_EVENT" />
</logger>

Logger logger = LoggerFactory.getLogger("wt_dig");
如果需要输出到指定的文件里面:log4j的配置为:

log4j.logger.wt_dig=INFO, myappenderdao
log4j.additivity.wt_dig=false

log4j.appender.myappenderdao=org.apache.log4j.DailyRollingFileAppender
log4j.appender.myappenderdao.DatePattern='.'yyyy-MM-dd
log4j.appender.myappenderdao.File=C:\\logdemo\\dao.log
log4j.appender.myappenderdao.layout=org.apache.log4j.PatternLayout
log4j.appender.myappenderdao.layout.ConversionPattern=%-6r %d{ISO8601} %-5p %40.40c %x - %m\n

格式化日志 %s,代表字符串
String.format("Can't find field config by bt : %s", bt);

%d,代码数字
String.format("Journal sources excel analysis error, execBatchId : %d", execBatch.getId())

%s 字符串类型 "mingrisoft"

%c 字符类型 'm'

%b 布尔类型 true

%d 整数类型(十进制)99

%x 整数类型(十六进制)FF

%o 整数类型(八进制)77

%f 浮点类型99.99

%a 十六进制浮点类型 FF.35AE

%e 指数类型9.38e+5

%g 通用浮点类型(f和e类型中较短的)
 
%h 散列码

%% 百分比类型%

%n 换行符

%tx 日期与时间类型(x代表不同的日期与时间转换符

String str=null;  
    str=String.format("Hi,%s", "王力");  
    System.out.println(str);  
    str=String.format("Hi,%s:%s.%s", "王南","王力","王张");            
    System.out.println(str);                           
    System.out.printf("字母a的大写是:%c %n", 'A');  
    System.out.printf("3>7的结果是:%b %n", 3>7);  
    System.out.printf("100的一半是:%d %n", 100/2);  
    System.out.printf("100的16进制数是:%x %n", 100);  
    System.out.printf("100的8进制数是:%o %n", 100);  
    System.out.printf("50元的书打8.5折扣是:%f 元%n", 50*0.85);  
    System.out.printf("上面价格的16进制数是:%a %n", 50*0.85);  
    System.out.printf("上面价格的指数表示:%e %n", 50*0.85);  
    System.out.printf("上面价格的指数和浮点数结果的长度较短的是:%g %n", 50*0.85);  
    System.out.printf("上面的折扣是%d%% %n", 85);  
    System.out.printf("字母A的散列码是:%h %n", 'A');  

参考链接:https://www.cnblogs.com/Dhouse/p/7776780.html

使用MessageFormat进行格式化代码,对应小数,只会保留2位;
比如123.0098就会变成123.01
必要要使用 {}进行占位,从0开始

String msg = MessageFormat.format(
                "current work no is {0},jeCreatedBy is {1},don't allow commit approval", 123.0098,
                "textst");
bean拷贝

1、BeanCopier只拷贝名称和类型都相同的属性。 
使用案例
 BeanCopier beanCopier = BeanCopier.create(SacAccountEntry.class, SacAccountEntryVo.class, false);
 beanCopier.copy(entry, accountEntryVo, null);

SacAccountEntry   来源

SacAccountEntryVo 目标

2、BeanUtils的拷贝

 BeanUtils.copyProperties(item, config);

 item  来源

 config 目标

多个集合,取并集/交集

 List<Set<String>> newStandard = new ArrayList<>();
        Set<String> s1 = new HashSet<>();
        s1.add("k1");
        s1.add("k2");
        Set<String> s2 = new HashSet<>();
        s1.add("k1");
        s1.add("k2");
        s1.add("k5");
        newStandard.add(s1);
        newStandard.add(s2);
        Optional<Set<String>> reduce = newStandard.parallelStream().reduce((a, b) -> {
            a.addAll(b);
            return a;
        });
        // 取并集后的字段
        Set<String> finalField = reduce.orElse(new HashSet<>());
        for (String s : finalField) {
            System.out.println(s);
        }

        System.out.println(">>>>>>>>>>>>>>>>");

        List<Set<String>> standard = new ArrayList<>();
        Set<String> k1 = new HashSet<>();
        k1.add("k1");
        k1.add("k2");
        Set<String> k2 = new HashSet<>();
        k2.add("k1");
        k2.add("k2");
        k2.add("k5");
        Set<String> k3 = new HashSet<>();
        k3.add("k2");
        standard.add(k1);
        standard.add(k2);
        standard.add(k3);
        Optional<Set<String>> reduceData = standard.parallelStream().reduce((a, b) -> {
            a.retainAll(b);
            return a;
        });
        // 取交集后的字段
        Set<String> field = reduceData.orElse(new HashSet<>());
        for (String s : field) {
            System.out.println(s);
        }
apach的字符串工具类
tempListAlias 集合;Constants.COMMA 分割符
1、字符拼接
StringUtils.join(tempListAlias, Constants.COMMA)
⚠️ **GitHub.com Fallback** ⚠️