项目自学记录8


项目自学记录8

断言的使用

断言在判断非空

 AssertUtils.assertNotNull(bean, "缺失bean对象,name=" + beanName);
 AssertUtils.assertNotNull(formatFile, "版式文件生成失败");

调用本类方法,其事务不生效

所以要新增一个类去调用别的类的方法。

数据库建表时关于varchar(256)与varchar(255)的讨论

在4.0版本以下,varchar(255)指的是255个字节,使用1个字节存储长度即可。当大于等于256时,要使用2个字节存储长度。所以定义varchar(255)比varchar(256)更好。
但是在5.0版本以上,varchar(255)指的是255个字符,每个字符可能占用多个字节,例如使用UTF8编码时每个汉字占用3字节,使用GBK编码时每个汉字占2字节。
NOTE:在生产环境我们一般用utf8mb4字符集。

文件路径要使用’/‘而不是’\\‘

对于linux系统,盘符不是\\,而是/

然后用/的话本地跑不起来,要用File.separator

二选一的注入

首先写了一个配置类

@Configuration
public class KaptchaConfig {
    @Bean
    public DefaultKaptcha getDefaultKaptcha() {
    }
    
    @Bean
    public DefaultKaptcha getWebKaptcha(){}
}

然后在controller中是这么注入的

@RestController
@RequestMapping("/kaptcha")
public class KaptchaController {

    @Qualifier("getDefaultKaptcha")
    @Autowired
    DefaultKaptcha defaultKaptcha;
}

访问jar包内的资源-打jar包后访问资源失败

jar包内的,我们得到的路径

file:\D:\developer_tools\repository\com\zbiti\anvil\vat\tools\ofd\invoice-ofd-creator\2.1.0-SNAPSHOT\invoice-ofd-creator-2.1.0-SNAPSHOT.jar!\shui.png

在子模块独立运行我们得到的路径

file:/D:/company/zbiti-sdk-ofd-v2/target/classes/shui.png

因为jar包下有.jar!,这个冒号,导致一般的文件或者文件名,可能会导致打开失败。

应该直接用流去做。(Java的流实在是tql)当然中间也可以用类加载器。

    private byte[] getQrImageData() throws IOException {
        String content = invoiceInfoDomain.getGraphCode();

        BufferedImage image = null;
        InputStream resource = DocumentResXmlCreater.class.getClassLoader().getResourceAsStream("shui.png");
        if (!Objects.isNull(resource) ) {
            image = ZXingQRCodeUtils.createQRCodeWithLogo(content,resource);
        } else {
            image = ZXingQRCodeUtils.createQRCode(content);
        }

        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        ImageIO.write(image, "png", bao);
        return bao.toByteArray();
    }

这样可以保证在ofd-v2的测试程序和vat-back里有jar包的情况下都可以运行。

如何在外面给一个类的内部类赋值

public class OuterClass {
    private int outerVariable = 10;
    
    public class InnerClass {
        private int innerVariable = 20;

        public void setInnerVariable(int value) {
            this.innerVariable = value;
        }

        public int getInnerVariable() {
            return innerVariable;
        }
    }

    public InnerClass getInnerClassInstance() {
        return new InnerClass();
    }
}

public class Main {
    public static void main(String[] args) {
        OuterClass outer = new OuterClass();

        // 获取内部类的实例
        OuterClass.InnerClass inner = outer.getInnerClassInstance();

        // 修改内部类的变量
        inner.setInnerVariable(30);

        // 输出内部类的变量
        System.out.println(inner.getInnerVariable());  // 输出:30
    }
}

里面写一个getInnerClassInstance。不然外面不能直接设置内部类里的属性。

selectByMap()要用invId,而不是inv_id

要用类字段而不是数据库字段

当然还是要看底层sql是咋写的。

在一些文件中,调用数组的size之前,也应该判断是否为Null

排查空指针异常的时候发现的。

在一个底层函数里面写了for(i = 0; i < vatInvoiceXMLDomain.getUndefinedLabelList().size(); ++i)

结果null指针。因为这个List压根没赋值。

应该先判断这个List是否为Null

所有三段的,都要判断中间那个变量是否为Null

比如这种

+vatInvoiceXMLDomain.getTaxSupervisionInfo().getInvoiceNumber()

要判断

vatInvoiceXMLDomain.getTaxSupervisionInfo()!=null

如果打断点失败,应该重启

打断的变灰,说明项目走不到这里。应该重启让他重新编译一下。

数据库插入数据,如果需要删除旧数据,使用replace into

不要用update,尤其是在有自增主键的情况下。

replace into 判断数据是否”存在”的机制是:被插入的数据是否违反主键索引或者唯一键索引约束。如果两者都没有违反的话,就进行插入操作,如果有违反的话,就会执行”替换”操作,这里的替换所做的事情是:先删除,在插入

删除:删除所有会产生以上所说的冲突的数据行。

插入:此时可以将 replace into 看成 insert into 语句。

replace into 和 insert into on duplicate key update 的区别

但是也要考虑其他的业务方面的一致性

解决跨包调用问题,使用接口

上面想调用下面,调用失败。则建立一个接口,让上面的类调用上面的接口。下面的类实现上面的接口。

Pgsql的时间做减法

因为服务器上时间是错误的,所以要在Java本地去new Date(),然后以nowDate为参数名字传入sql中。

Cause: org.postgresql.util.PSQLException: ERROR: operator does not exist: timestamp without time zone < interval

项目用的 PostgreSQL 数据库,使用 SpringBoot + Mybatis 整合

where main.create_time (#{nowDate} - INTERVAL ‘1 minute’);报错

改为下面这种,要加::timestamp才能做减法

where main.create_time  <![CDATA[<]]> #{nowDate}::timestamp - interval '1 minute';

对页面的表格数据变为Excel下载

    @RequestMapping("/exportInvoiceList")
    public void exportData(IntaxInvoiceDTO intaxInvoiceDTO, HttpServletRequest request, HttpServletResponse response) throws IOException {
        List<IntaxInvoiceVO> dataList =intaxInvoiceService.exportInvoiceList(intaxInvoiceDTO);
        ExcelUtils.exportExcel(String.format("异常开票管理-%s", DateUtils.getCurrentDateTimeStrWithoutSplit()), "异常发票数据", dataList,IntaxInvoiceVO.class, request, response);
    }

最核心的就是ExcelUtils.exportExcel函数,第三个参数,数据列表,第四个参数,这个数据属于哪个类。

/**
 * 导出Excel(单Sheet页数据)
 *
 * @param fileName  文件名
 * @param sheetName Sheet页名
 * @param data      导出的数据
 * @param clazz     类型
 * @param request   请求
 * @param response  响应
 * @param <T>       类型模板
 * @throws IOException IO异常
 */
public static <T> void exportExcel(final String fileName, final String sheetName, final List<T> data, final Class<T> clazz, final HttpServletRequest request, final HttpServletResponse response) throws IOException {
    ExcelSheetDomain<T> excelSheetDomain = new ExcelSheetDomain<>(sheetName, data, clazz);
    exportExcel(fileName, excelSheetDomain, request, response);
}

然后整个文件在vat-base里的ExcelUtils。


文章作者: 爱敲代码の鱼儿
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 爱敲代码の鱼儿 !
  目录