java - 在 log4j2 jdbcappender 中设置日期时如何处理 null?

标签 java jdbc log4j2 appender

当我在日期列中设置空值时,我在表中得到“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="%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>

开始日期和结束日期列的数据类型是日期时间

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), "");

空值字符串也是如此。

最佳答案

插入 null

我认为使用 JDBCAppender 和这样的模式不可能将 null 放入任何类型的任何列中。

This thread几年前突然出现,然后是this Jira issue .这些似乎都没有引起任何注意。

简短的版本是 StringBuilder 在模式和准备好的语句之间使用,因此 INSERT 总是得到一个非空字符串,即使(在你的例子中) nullThreadContext 中的值。因此可以插入空字符串或字符串 "null",但似乎无法插入 value null.

1900 年 1 月 1 日

当我针对 MySQL 数据库运行您的示例时,插入会预先失败,因为 MySQL 不知道如何从空字符串构造 DATETIME

我猜您正在使用 SQL Server,它会很乐意将空字符串转换为 1900-01-01 00:00:00.000,因为当然这就是你的意思。

无论您使用什么数据库,JDBCAppender 都会用非空字符串填充 INSERT 语句。从那里发生的事情因数据库而异。

为什么?

乍一看,框架正在将您的值 (null) 更改为另一个值(空字符串),这似乎很奇怪。然而,从本质上讲,日志记录关于文本字符串的。

是的,有一个 appender 可以将这些字符串写入数据库。是的,您的数据库可以反过来将这些字符串转化为 DATETIMEINTEGER 等类型。但对于任何给定的 appender,它实际上只是关于操作和输出字符串。

可能的解决方法

如果您真的想使用JDBCAppendernull 放入数据库,您可以write a trigger .

最终观察

不确定这是否有帮助,但我不妨介绍一下我的所有发现:

在 log4j 配置中使用 ColumnMapping 而不是 Column 允许您指定类名。此类名称的存在(或不存在)和值确实会更改插入到数据库中的值。例如,使用 SQL Server Express 2014:

<ColumnMapping name="startdate" pattern="%X{startdate}" type="java.sql.Timestamp"/>

startdate 为 null 而不是 1900-01-01 时,将导致记录当前日期和时间。使用 java.sql.Date 将记录不带时间的当前日期。

关于java - 在 log4j2 jdbcappender 中设置日期时如何处理 null?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47573135/

相关文章:

java - URL 构造函数中的端口

Java Swing : prevent Components to update enabled state until I tell them to

java - 使用java在访问表中搜索值

java - MySQL JDBC 负载平衡和故障转移

java - 使用 Java-JDBC 从 Oracle 数据库读取数据时的字符编码

intellij-idea - maven 构建后 IntelliJ IDEA 将找不到 log4j2.xml

java - 如何在log4j中自动折叠重复的日志输出

java - 通过折叠所有元素来删除二维数组中的元素

java - 如何修复 Retrofit 中的 Expected BEGIN_OBJECT?

java - 带时间的日志文件名不能正常工作