简体   繁体   English

使用Log4j2在MySQL中获取语法错误(XML Config)

[英]Getting syntax error (XML Config) in MySQL using Log4j2

I am currently working on my Spring project to create simple library portal (just for education purposes). 我目前正在从事Spring项目,以创建简单的图书馆门户(仅出于教育目的)。 And now I am struggling with logging some actions into MySQL database using Log4j2 JDBCAppender. 现在,我正在努力使用Log4j2 JDBCAppender将一些操作记录到MySQL数据库中。

To do that, I have created table in my database, using query: 为此,我使用查询在数据库中创建了表:

CREATE TABLE user_logs (
  `id` int(12) NOT NULL AUTO_INCREMENT,
  `level` varchar(10) NOT NULL,
  `dated` TIMESTAMP NOT  NULL DEFAULT CURRENT_TIMESTAMP,
  `username` varchar(64) NOT NULL,
  `field` varchar(60) NOT NULL,
  `from` varchar(1000) NOT NULL DEFAULT '',
  `to` varchar(1000) NOT NULL DEFAULT '',
  `message` varchar(500) NOT NULL,

   PRIMARY KEY (`id`),

   KEY `user` (`username`),
   CONSTRAINT `FK_USERNAME` FOREIGN KEY (`username`)
   REFERENCES `user` (`username`)
   ON DELETE NO ACTION ON UPDATE NO ACTION

)ENGINE=InnoDB DEFAULT CHARSET=utf8;

In database I want to store information what field was modified, from which and to which value it was changed. 在数据库中,我想存储信息:修改了哪个字段,从哪个字段更改为哪个值。 Also logs will contain information for which user there was a change. 此外,日志还将包含发生更改的用户的信息。

Then I created Log4j2 XML config file: 然后,我创建了Log4j2 XML配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration name="ChangesLogs">
<Appenders>

    <Console name="consoleAppender" target="SYSTEM_OUT">
        <PatternLayout pattern="%d | %level | %logger | %m" />
    </Console>

    <JDBC name="userAppenderDB" tableName="user_logs">
        <ConnectionFactory class="com.wkrzywiec.spring.library.config.LogsConnectionFactory" method="getDatabaseConnection" />
        <Column name="level" pattern="%level"/>
        <Column name="username" pattern="%X{username}"/>
        <Column name="field" pattern="%X{field}"/>
        <Column name="from" pattern="%X{from}"/>
        <Column name="to" pattern="%X{to}"/>
        <Column name="message" pattern="%message"/>
    </JDBC>
</Appenders>

<Loggers>
    <Root level="debug">
        <AppenderRef ref="consoleAppender" />
    </Root>

    <Logger name="userLoggerDB" >
        <AppenderRef ref="consoleAppender" />
        <AppenderRef ref="userAppenderDB" />
    </Logger>

</Loggers>

And class for JDBCAppender connection pool: 和JDBCAppender连接池的类:

package com.wkrzywiec.spring.library.config;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnection;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.springframework.stereotype.Component;

@Component
public class LogsConnectionFactory {

    private static interface Singleton {
        final LogsConnectionFactory INSTANCE = new LogsConnectionFactory();
    }

    private final DataSource dataSource;

    private String datasourceURL = "jdbc:mysql://localhost:3306/library_db?autoReconnect=true&useSSL=false&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC";

    private String userName = "library-spring";

    private String pass = "library-spring";

    private LogsConnectionFactory() {

        Properties properties = new Properties();
        properties.setProperty("user", userName);
        properties.setProperty("password", pass);

        GenericObjectPool<PoolableConnection> pool = new GenericObjectPool<PoolableConnection>();
        DriverManagerConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
                datasourceURL, properties);

        new PoolableConnectionFactory(connectionFactory, pool, null, "SELECT 1", 3, false, false, Connection.TRANSACTION_READ_COMMITTED);

        this.dataSource = new PoolingDataSource(pool);
    }

    public static Connection getDatabaseConnection() throws SQLException {
        return Singleton.INSTANCE.dataSource.getConnection();
    }

}

And finally when I am saving new user using below code in my service class: 最后,当我在服务类中使用以下代码保存新用户时:

@Override
public void saveReaderUser(UserDTO user) {
    com.wkrzywiec.spring.library.entity.User userEntity = convertUserDTOtoUserEntity(user);
    userDAO.saveUser(userEntity);

    ThreadContext.put("username", user.getUsername());
    ThreadContext.put("field", "ALL");
    ThreadContext.put("from", "");
    ThreadContext.put("to", user.toString());
    userLogger.info("New user");
    ThreadContext.clearAll();
}

I've got this error (just to make it clear, this error is only for adding logs, user is successfully saved in db): 我遇到了这个错误(为清楚起见,此错误仅用于添加日志,用户已成功保存在db中):

Caused by: java.sql.BatchUpdateException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from,to,message) VALUES ('INFO','wojtek21','ALL','','UserDTO [username=wojtek21,' at line 1
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.cj.core.util.Util.handleNewInstance(Util.java:185)
    at com.mysql.cj.core.util.Util.getInstance(Util.java:168)
    at com.mysql.cj.core.util.Util.getInstance(Util.java:175)
    at com.mysql.cj.jdbc.exceptions.SQLError.createBatchUpdateException(SQLError.java:636)
    at com.mysql.cj.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1734)
    at com.mysql.cj.jdbc.PreparedStatement.executeBatchInternal(PreparedStatement.java:1217)
    at com.mysql.cj.jdbc.StatementImpl.executeBatch(StatementImpl.java:1009)
    at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
    at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
    at org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager.commitAndClose(JdbcDatabaseManager.java:172)
    ... 59 more

Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from,to,message) VALUES ('INFO','wojtek21','ALL','','UserDTO [username=wojtek21,' at line 1
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:536)
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:513)
    at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:115)
    at com.mysql.cj.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:1983)
    at com.mysql.cj.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1826)
    at com.mysql.cj.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2034)
    at com.mysql.cj.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1712)
    ... 64 more

2018-03-04 10:07:44,726 http-bio-8080-exec-7 ERROR An exception occurred processing Appender userAppenderDB org.apache.logging.log4j.core.appender.AppenderLoggingException: Failed to commit transaction logging event or flushing buffer.
    at org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager.commitAndClose(JdbcDatabaseManager.java:177)
    at org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager.write(AbstractDatabaseManager.java:174)
    at org.apache.logging.log4j.core.appender.db.AbstractDatabaseAppender.append(AbstractDatabaseAppender.java:108)
    at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:156)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:129)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:120)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:84)
    at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:448)
    at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:433)
    at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:417)
    at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:403)
    at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:63)
    at org.apache.logging.log4j.core.Logger.logMessage(Logger.java:146)
    at org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2163)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessageTrackRecursion(AbstractLogger.java:2118)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2101)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:1995)
    at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1967)
    at org.apache.logging.log4j.spi.AbstractLogger.info(AbstractLogger.java:1304)
    at com.wkrzywiec.spring.library.service.LibraryUserDetailService.saveReaderUser(LibraryUserDetailService.java:86)
    at com.wkrzywiec.spring.library.controller.LoginController.processRegisterForm(LoginController.java:58)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:871)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:777)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:881)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:209)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:94)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:502)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1132)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:283)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

Caused by: java.sql.BatchUpdateException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from,to,message) VALUES ('INFO','wojtek21','ALL','','UserDTO [username=wojtek21,' at line 1
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.cj.core.util.Util.handleNewInstance(Util.java:185)
    at com.mysql.cj.core.util.Util.getInstance(Util.java:168)
    at com.mysql.cj.core.util.Util.getInstance(Util.java:175)
    at com.mysql.cj.jdbc.exceptions.SQLError.createBatchUpdateException(SQLError.java:636)
    at com.mysql.cj.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1734)
    at com.mysql.cj.jdbc.PreparedStatement.executeBatchInternal(PreparedStatement.java:1217)
    at com.mysql.cj.jdbc.StatementImpl.executeBatch(StatementImpl.java:1009)
    at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
    at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
    at org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager.commitAndClose(JdbcDatabaseManager.java:172)
    ... 59 more

Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from,to,message) VALUES ('INFO','wojtek21','ALL','','UserDTO [username=wojtek21,' at line 1
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:536)
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:513)
    at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:115)
    at com.mysql.cj.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:1983)
    at com.mysql.cj.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1826)
    at com.mysql.cj.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2034)
    at com.mysql.cj.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1712)
    ... 64 more

I've tried many things to solve it (checking typo, other configs, data types in sql table, etc), but with no success. 我已经尝试了很多方法来解决它(检查输入错误,其他配置,sql表中的数据类型等),但是没有成功。 From the error message it looks like that it is a problem with SQL insert query, but I don't know how to fix it as it is generated by Log4j2. 从错误消息中看,这似乎是SQL插入查询的问题,但是由于Log4j2生成的错误,我不知道如何解决。 Do you know what I am doing wrong? 你知道我在做什么错吗?

I would really appreciate your support. 非常感谢您的支持。

Thanks a lot! 非常感谢!

from is a SQL keyword. from是一个SQL关键字。 Don't use that as a column name. 不要将其用作列名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM