[英]How to handle null while setting date in log4j2 jdbcappender?
When I set null value in the date column I get "1900-01-01 00:00:00.000" value in my table and I am expecting NULL in that column. 当我在日期列中设置空值时,我在表中获得“ 1900-01-01 00:00:00.000”值,并且我期望该列中为NULL。 As this is handled properly in jdbc if I put like this
因为如果我这样把它在jdbc中正确处理
preparedStatement.setBindParam(Types.TIMESTAMP, 12, startdate);
log4j2.xml 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="%X{ID}" isUnicode="false"/>
<Column name="startdate" pattern="%X{startdate}" isUnicode="false"/>
<Column name="enddate" pattern="%X{enddate}" isUnicode="false"/>
</JDBC>
</Appenders>
<Loggers>
<Root level="trace" includeLocation="false">
<AppenderRef ref="myAppender" level="TESTLOG" />
</Root>
</Loggers>
</Configuration>
Datatype of columns startdate and enddate is datetime 起始日期和结束日期列的数据类型为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), "");
The same is for String with null value. 对于具有null值的String也是一样。
Inserting null 插入空值
I don't think it's possible to get null
into any column of any type using JDBCAppender
with patterns like this. 我认为使用
JDBCAppender
的模式不可能将null
插入任何类型的任何列中。
This thread popped up a couple of years ago, followed by this Jira issue . 此线程在几年前突然出现,随后出现了《 吉拉》杂志 。 None of it seems to have gotten any attention.
它似乎都没有引起任何注意。
The short version is that a StringBuilder
is used between pattern and prepared statement, and thus the INSERT
always gets a non-null string, even if (in your example) null
is the value in the ThreadContext
. 简短的版本是在模式和准备好的语句之间使用
StringBuilder
,因此INSERT
始终获取非空字符串,即使(在您的示例中) ThreadContext
的值为null
。 So it's possible to insert an empty string, or the string "null"
, but it doesn't appear to be possible to insert the value null
. 因此可以插入一个空字符串或字符串
"null"
,但似乎无法插入值 null
。
January 1, 1900 1900年1月1日
When I run your example against a MySQL database, the insert fails up front, because MySQL doesn't know how to construct a DATETIME
from an empty string. 当我对一个MySQL数据库运行您的示例时,该插入操作会预先失败,因为MySQL不知道如何从一个空字符串构造一个
DATETIME
。
I'm guessing you're using SQL Server, which will happily turn an empty string into 1900-01-01 00:00:00.000
, because of course that's what you meant. 我猜你使用SQL Server,它会高兴地把一个空字符串为
1900-01-01 00:00:00.000
, 自然是因为那是你的意思的 。
Regardless of the database you use, JDBCAppender
is going to fill the INSERT
statement with non-null strings. 无论使用哪种数据库,
JDBCAppender
都将用非空字符串填充INSERT
语句。 What happens from there will vary from DB to DB. 从那里发生的事情将因数据库而异。
Why? 为什么?
At first it may seem strange that the framework is changing your value ( null
) to another value (empty string). 刚开始,框架将您的值(
null
)更改为另一个值(空字符串)似乎很奇怪。 However, at its core, logging is about strings of text. 但是,日志记录的核心是文本字符串。
Yes, there's an appender that will write these strings to a database. 是的,有一个追加程序会将这些字符串写入数据库。 And yes, your database can in turn coax those strings into types like
DATETIME
or INTEGER
. 是的,您的数据库又可以将这些字符串哄骗成
DATETIME
或INTEGER
类的类型。 But to any given appender, it's all really just about manipulating and outputting strings. 但是对于任何给定的附加程序,这实际上只是关于操作和输出字符串。
Possible work-around 可能的解决方法
If you really want to get null
into the database using JDBCAppender
, you may be able to write a trigger . 如果您确实想使用
JDBCAppender
将null
放入数据库中,则可以编写触发器 。
Final Observation 最终观察
Not sure if this helps any, but I may as well present all my findings: 不确定这是否有帮助,但我也可以介绍我的所有发现:
Using ColumnMapping
instead of Column
in your log4j config allows you to specify a class name. 在您的log4j配置中使用
ColumnMapping
而不是Column
可以指定类名。 The presence (or absence) and value of this class name does change the value that is inserted into the database. 该类名的存在(或不存在)和值的确会更改插入数据库中的值。 For example, using SQL Server Express 2014:
例如,使用SQL Server Express 2014:
<ColumnMapping name="startdate" pattern="%X{startdate}" type="java.sql.Timestamp"/>
Will cause the current date and time to be logged when startdate
is null, instead of 1900-01-01. 当
startdate
为null而不是1900-01-01时,将导致记录当前日期和时间。 Using java.sql.Date
instead will log the current date without time. 相反,使用
java.sql.Date
将记录当前日期,而无需时间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.