在 log4j2 jdbcapender 中设置日期时如何处理 null?
Posted
技术标签:
【中文标题】在 log4j2 jdbcapender 中设置日期时如何处理 null?【英文标题】:How to handle null while setting date in log4j2 jdbcappender? 【发布时间】:2017-11-30 12:07:12 【问题描述】:当我在日期列中设置空值时,我在表中得到“1900-01-01 00:00:00.000”值,并且我期望该列中为 NULL。 因为如果我这样放的话,这在 jdbc 中得到了正确处理
preparedStatement.setBindParam(Types.TIMESTAMP, 12, startdate);
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug">
<CustomLevels>
<CustomLevel name="TESTLOG" intLevel="552" />
</CustomLevels>
<Appenders>
<JDBC name="myAppender" tableName="MYTABLE">
<DataSource jndiName="java:MyDataSource" />
<Column name="ID" pattern="%XID" isUnicode="false"/>
<Column name="startdate" pattern="%Xstartdate" isUnicode="false"/>
<Column name="enddate" pattern="%Xenddate" isUnicode="false"/>
</JDBC>
</Appenders>
<Loggers>
<Root level="trace" includeLocation="false">
<AppenderRef ref="myAppender" level="TESTLOG" />
</Root>
</Loggers>
</Configuration>
startdate 和 enddate 列的数据类型是 datetime
ThreadContext.put("startdate", startdate != null ? startdate.toString() : null);
ThreadContext.put("enddate", a_reportEndDate != null ? enddate.toString() : null);
final Logger LOGGER = LogManager.getLogger();
LOGGER.log(Level.forName("TESTLOG", 552), "");
对于空值的字符串也是如此。
【问题讨论】:
也许您的表是使用时间戳列的默认值创建的? 【参考方案1】:插入空值
我认为使用JDBCAppender
和这样的模式不可能将null
放入任何类型的任何列中。
This thread 是几年前出现的,紧随其后的是 this Jira issue。似乎都没有引起任何注意。
简短的版本是在模式和准备好的语句之间使用StringBuilder
,因此INSERT
总是得到一个非空字符串,即使(在你的例子中)null
是@中的值987654329@。所以可以插入一个空字符串,或者字符串"null"
,但是好像不能插入值null
。
1900 年 1 月 1 日
当我针对 mysql 数据库运行您的示例时,插入预先失败,因为 MySQL 不知道如何从空字符串构造 DATETIME
。
我猜你正在使用 SQL Server,它会很高兴地将一个空字符串转换为 1900-01-01 00:00:00.000
,因为当然这就是你的意思。
无论您使用什么数据库,JDBCAppender
都会用非空字符串填充INSERT
语句。从那里发生的事情因数据库而异。
为什么?
起初,框架将您的值 (null
) 更改为另一个值(空字符串)可能看起来很奇怪。然而,就其核心而言,日志记录是关于文本字符串的。
是的,有一个附加程序可以将这些字符串写入数据库。是的,您的数据库可以反过来将这些字符串转化为DATETIME
或INTEGER
之类的类型。但是对于任何给定的 appender,它实际上只是关于操作和输出字符串。
可能的解决方法
如果您真的想使用JDBCAppender
将null
输入数据库,您可以使用write a trigger。
最终观察
不确定这是否有帮助,但我不妨介绍一下我的所有发现:
在 log4j 配置中使用 ColumnMapping
而不是 Column
允许您指定类名。此类名称的存在(或不存在)和值确实会更改插入到数据库中的值。例如,使用 SQL Server Express 2014:
<ColumnMapping name="startdate" pattern="%Xstartdate" type="java.sql.Timestamp"/>
当startdate
为空时,将记录当前日期和时间,而不是 1900-01-01。改用java.sql.Date
将记录当前日期而没有时间。
【讨论】:
由于我使用的是 java 6,并且 log4j-core-2.3.jar 不支持 ColumnMapping以上是关于在 log4j2 jdbcapender 中设置日期时如何处理 null?的主要内容,如果未能解决你的问题,请参考以下文章
在 Spring Boot 应用程序中未针对休眠和弹簧过滤 Log4j2 日志级别