lottery lec7-cnblog

发布时间 2024-01-07 20:41:18作者: xyfyy

lottery lec7

protected Logger logger = LoggerFactory.getLogger(DistributionBase.class);

今天突然,对这段代码感觉很疑惑,为什么获取Logger类需要这样?传入当前类的class文件作用是什么?在之前使用C++的开源日志库glog的时候,只需要初始化好日志库需要的属性,然后直接LOG(ERROR) << 来使用即可。

解答问题:

传入class后,在打印日志时候可以知道该条日志具体的类,从而方便排查错误

在网上,查看其它logger获取通常采用这种修饰:

private static final Logger LOGGER = LoggerFactory.getLogger(xxx.class);

// 具体原因:
private:因为LOGGER对象只能在当前类中使用,避免其他类调用(存在一种情况:大量的类中的日志都是上述写法,连对象名LOGGER都一样,所以采用private可以有效避免其他类调用)。
    
static:用static定义,在xxx类被加载时,LOGGER作为静态对象,只会在创建一次且唯一,可避免重复;但如果是非静态对象,其他类引用xxx类时,LOGGER对象会再次创建,会造成内存浪费。
    
final:因为final可以避免LOGGER对象被修改,尤其是如果xxx.class字节码信息被修改,会导致,打印日志出现紊乱,与类不一致。

同时,通过查阅了解到了另一个信息:之前一直以为slf4j是日志库,实际上slf4j是一个日志框架,其定义了日志接口出来,可以采用其具体的实现类(Logger类以及LoggerFactory类)去完成日志的打印。

mysql问题

在执行更改表语句时,遇到了问题:

CREATE TABLE `activity` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
  `activity_id` bigint(20) NOT NULL COMMENT '活动ID',
  `activity_name` varchar(64) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '活动名称',
  `activity_desc` varchar(128) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '活动描述',
  `begin_date_time` datetime(3) DEFAULT NULL COMMENT '开始时间',
  `end_date_time` datetime(3) DEFAULT NULL COMMENT '结束时间',
  `stock_count` int(11) DEFAULT NULL COMMENT '库存',
  `stock_surplus_count` int(11) DEFAULT NULL COMMENT '库存剩余',
  `take_count` int(11) DEFAULT NULL COMMENT '每人可参与次数',
  `strategy_id` bigint(11) DEFAULT NULL COMMENT '抽奖策略ID',
  `state` tinyint(2) DEFAULT NULL COMMENT '活动状态:1编辑、2提审、3撤审、4通过、5运行(审核通过后worker扫描状态)、6拒绝、7关闭、8开启',
  `creator` varchar(64) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '创建人',
  `create_time` datetime(3) DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime(3) DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_activity_id` (`activity_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='活动配置';


Error信息:1067 - Invalid default value for 'create_time'

字面意思,create_time的默认值CURRENT_TIMESTAMP无效..

在解决过程中首先看网上有人说因为sql_mode中设置了时间不能为0,抱着试一试的态度,修改了sql_mode,问题依旧。

然后看到了datetime(3),对这个3感觉挺好奇的。这个3的作用是什么呢?

3 表示的是毫秒的精度,当我们改为CURRENT_TIMESTAMP(3)即可成功建表,当然,也可以将datetime的3去掉,即表示不显示毫秒值,个人认为在很多业务场景中对毫秒值应该没有必要去存储,大多数情况使用datetime即可。

sql_mode

sql_mode应该是Mysql中对sql语法的一个额外约束配置项。

# 查看当前的sql_mode
show variables like 'sql_mode';

# 修改方式
SET GLOBAL sql_mode = 'modes...';
SET SESSION sql_mode = 'modes...';
# GLOBAL和SESSION的区别:SESSION是在本次连接期间有用,GLOBAL是作用于本次服务,只要mysql不重启,GLOBAL的变量一直有效
或者在my.ini中设置
[mysqld]
sql_mode=STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
sql_mode常见值:
ONLY_FULL_GROUP_BY: 对于GROUP BY聚合操作,如果在SELECT中的列,没有在GROUP BY中出现,那么这个SQL是不合法的,因为列不在GROUP BY从句中
NO_AUTO_VALUE_ON_ZERO: 该值影响自增长列的插入。默认设置下,插入0或NULL代表生成下一个自增长值。如果用户希望插入的值为0,而该列又是自增长的,那么这个选项就有用了。
STRICT_TRANS_TABLES:在该模式下,如果一个值不能插入到一个事务中,则中断当前的操作,对非事务表不做限制
NO_ZERO_IN_DATE:在严格模式下,不允许日期和月份为零
NO_ZERO_DATE:设置该值,mysql数据库不允许插入零日期,插入零日期会抛出错误而不是警告
ERROR_FOR_DIVISION_BY_ZERO:在insert或update过程中,如果数据被零除,则产生错误而非警告。如果未给出该模式,那么数据被零除时Mysql返回NULL
NO_AUTO_CREATE_USER:禁止GRANT创建密码为空的用户
NO_ENGINE_SUBSTITUTION:如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,用默认的存储引擎替代,并抛出一个异常
PIPES_AS_CONCAT:将"||"视为字符串的连接操作符而非或运算符,这和Oracle数据库是一样是,也和字符串的拼接函数Concat想类似
ANSI_QUOTES:启用ANSI_QUOTES后,不能用双引号来引用字符串,因为它被解释为识别符

查看一下当前的sql_mode值:

image-20240107182329538

Mybatis问题

由于修改了表的字段名,需要去修改mapper配置文件中的sql语句。将所有字段修改为后,发现依据不能正常通过ut。经过debug后发现,select后的数据没有映射到对象中去,怀疑是mapper语句的中数据库记录和实体对象映射出现了问题。

可以通过resultMap来解决这个映射问题,思路很简单,看一下下面的图即可理解,通过column映射到property即可。

image-20240107203844764