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

时间:2017-11-30 12:07:13

标签: 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>

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

对于具有空值的String也是如此。

1 个答案:

答案 0 :(得分:2)

插入空

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

几年前出现了{p> This thread,然后是this Jira issue。似乎都没有引起任何关注。

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

1900年1月1日

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

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

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

<强>为什么吗

首先,框架将您的值(null)更改为另一个值(空字符串)似乎很奇怪。但是,在其核心,记录关于文本字符串。

是的,有一个将这些字符串写入数据库的appender。是的,您的数据库可以将这些字符串转换为DATETIMEINTEGER等类型。但对于任何给定的appender,它都只是操纵和输出字符串。

可能的解决方法

如果您真的想使用nullJDBCAppender导入数据库,您可以write a trigger

最终观察

不确定这是否有帮助,但我也可以提供我的所有发现:

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

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

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