当前位置: 首页 > 知识库问答 >
问题:

Hibernate JPA EntityManager创建额外的log4j appender?

冯星剑
2023-03-14

我写了一个简单的控制台应用程序,它使用JPA连接到MySQL数据库。数据的实际读写工作正常,但日志记录似乎被搞砸了。我创建的每个EntityManager实例似乎都将自己的log4j appender添加到控制台。因此,由于我的应用程序中有三个实体管理器实例,除了我想要的“真实”控制台输出行之外,我的控制台输出中还有三行额外的行。这里有一个例子。第一行来自我的“真正的”附件,另外三行似乎来自实体管理器的附件:

08:31:58,970 com.electricgearbox.app.ProcessDataItemApp DEBUG main foobar:169 - geoEntityDao.getByCompositeKey took 81 milliseconds 
0 [main] DEBUG foobar  - geoEntityDao.getByCompositeKey took 81 milliseconds 
0 [main] DEBUG foobar  - geoEntityDao.getByCompositeKey took 81 milliseconds 
0 [main] DEBUG foobar  - geoEntityDao.getByCompositeKey took 81 milliseconds 

下面是我的log4j配置:

log4j.rootCategory=WARN, mylog

log4j.appender.mylog=org.apache.log4j.ConsoleAppender
log4j.appender.mylog.layout=org.apache.log4j.PatternLayout
log4j.appender.mylog.layout.ConversionPattern=%d{ABSOLUTE} %C %5p %t %c{2}:%L - %m%n

log4j.category.foobar=DEBUG

我希望能够关闭这种行为,只需要获得我想要的控制台线路。我似乎无法“破解代码”如何做到这一点-任何帮助都将不胜感激。。。

补充信息:这里似乎发生了两件事。第一个是log4j appender可加性设置,默认情况下为true。重新阅读稀疏log4j留档(http://logging.apache.org/log4j/1.2/manual.html)我遇到了这个:

给定记录器的每个启用的日志记录请求都将转发给该记录器中的所有appender以及层次结构中更高的appender。

没有提到的是,它显然会这样做,不管层次结构中更高的记录器的设置如何。

这意味着,或者在我的例子中似乎意味着,尽管我的根记录器设置为WARN,但Hibernate类附加到它的附加程序仍然被DEBUG级别的消息所使用。这与我所期望的相反。我不确定这是否代表了Hibernate 4.0.1 JPA实现中的错误,或者只是log4j缺少留档,或者log4j和slf4j之间的故障(Hibernate使用)。

第二件事是,每次创建EntityManager对象时,它似乎都会向log4j日志树添加一个appender,因此如果有多个EntityManager,就会收到多条日志消息。我敢肯定这是Hibernate日志中的一个bug。

仍在寻找解释或示例,说明这种“可加性”如何在log4j中实际工作——它似乎与我从有限的文档中所期望的相反。也就是说,appender似乎是沿着日志树传递的,而不是向上传递日志事件。

以下是我到目前为止为我的(修订后的)log4j属性文件所做的,它似乎正在工作:

log4j.rootCategory=WARN, mylog

# logger "root" logs at WARN level to appender "mylog"
log4j.appender.mylog=org.apache.log4j.ConsoleAppender
log4j.appender.mylog.layout=org.apache.log4j.PatternLayout

# Logger "foobar" logs at DEBUG level to appender "bootylog"
log4j.category.foobar=DEBUG, bootylog

log4j.appender.bootylog=org.apache.log4j.ConsoleAppender
log4j.appender.bootylog.layout=org.apache.log4j.PatternLayout
log4j.appender.bootylog.layout.ConversionPattern=%d{ABSOLUTE} %C %5p %t %c{2}:%L - %m%n

# additivity is off
log4j.additivity.foobar=false
log4j.additivity.org.hibernate=false

这给了我以下输出,这正是我想要的:

11:15:43,622 com.electricgearbox.app.ProcessDataItemApp DEBUG main foobar:152 - geoDataItemDao.create took 5 milliseconds 
11:15:43,624 com.electricgearbox.app.ProcessDataItemApp DEBUG main foobar:166 - geoEntityDao.getByCompositeKey took 2 milliseconds 
11:15:43,626 com.electricgearbox.app.ProcessDataItemApp DEBUG main foobar:159 - dataEntityDao.getDataEntityByFieldCode took 1 milliseconds 

最后,我强烈建议任何对log4j有问题的人在运行应用程序时打开此命令行选项:

-Dlog4j.debug 

共有2个答案

高嘉树
2023-03-14

这里似乎发生了两件事。第一个是log4j appender additivity设置,默认情况下为true。重新阅读稀疏的log4j文档(http://logging.apache.org/log4j/1.2/manual.html)我遇到了这个:

给定记录器的每个启用的日志记录请求都将转发给该记录器中的所有appender以及层次结构中更高的appender。

没有提到的是,它显然会这样做,不管层次结构中更高的记录器的设置如何。

这意味着,或者在我的例子中似乎意味着,尽管我的根记录器设置为WARN,但Hibernate类附加到它的附加程序仍然被DEBUG级别的消息所使用。这与我所期望的相反。我不确定这是否代表了Hibernate 4.0.1 JPA实现中的错误,或者只是log4j缺少留档,或者log4j和slf4j之间的故障(Hibernate使用)。

第二件事是,每次创建EntityManager对象时,它似乎都会向log4j日志树添加一个appender,因此如果有多个EntityManager,就会收到多条日志消息。我敢肯定这是Hibernate日志中的一个bug。

仍在寻找解释或示例,说明这种“可加性”如何在log4j中实际工作——它似乎与我从有限的文档中所期望的相反。也就是说,appender似乎是沿着日志树传递的,而不是向上传递日志事件。

以下是我到目前为止为我的(修订后的)log4j属性文件所做的,它似乎正在工作:

log4j.rootCategory=WARN, mylog

# logger "root" logs at WARN level to appender "mylog"
log4j.appender.mylog=org.apache.log4j.ConsoleAppender
log4j.appender.mylog.layout=org.apache.log4j.PatternLayout

# Logger "foobar" logs at DEBUG level to appender "bootylog"
log4j.category.foobar=DEBUG, bootylog

log4j.appender.bootylog=org.apache.log4j.ConsoleAppender
log4j.appender.bootylog.layout=org.apache.log4j.PatternLayout
log4j.appender.bootylog.layout.ConversionPattern=%d{ABSOLUTE} %C %5p %t %c{2}:%L - %m%n

# additivity is off
log4j.additivity.foobar=false
log4j.additivity.org.hibernate=false

这给了我以下输出,这正是我想要的:

11:15:43,622 com.electricgearbox.app.ProcessDataItemApp DEBUG main foobar:152 - geoDataItemDao.create took 5 milliseconds 
11:15:43,624 com.electricgearbox.app.ProcessDataItemApp DEBUG main foobar:166 - geoEntityDao.getByCompositeKey took 2 milliseconds 
11:15:43,626 com.electricgearbox.app.ProcessDataItemApp DEBUG main foobar:159 - dataEntityDao.getDataEntityByFieldCode took 1 milliseconds 

最后,我强烈建议任何对log4j有问题的人在运行应用程序时打开此命令行选项:

-Dlog4j.debug 
史磊
2023-03-14

正如其他地方所回答的,尝试在log4j属性中更改hibernate的日志记录级别

例如

log4j.logger.org.hibernate=info
 类似资料:
  • 我的代码应该读取4列,将它们分成前2列的顶点和后两列的边缘属性。CSV文件在37行数据中有33个唯一顶点。我不明白的是为什么我得到74个顶点和37条边。有趣的是,如果我省略addE语句,我只得到37个顶点。 很明显,由于我一直在努力解决当前的问题,财产部分没有包括在内。 \t代表标签等。 我的代码是:

  • 问题内容: 我正在多线程环境中聚合键的多个值。密钥未知。我以为我会做这样的事情: 我看到的问题是,每次运行此方法时,我都需要创建一个新的实例,然后将其丢弃(在大多数情况下)。这似乎是对垃圾收集器的不合理滥用。是否有更好的,线程安全的方法来初始化这种结构而不必使用该方法?我对使该方法不返回新创建的元素的决定感到惊讶,并且对缺少除非被要求(可以这么说)实例化实例的延迟的方法感到惊讶。 问题答案: Ja

  • 有一个入口配置,比如 gke创建了nginx ingress负载平衡器,但也创建了另一个具有后端的负载平衡器,就像如果没有选择nginx,而是选择gcp作为ingress一样。 下面的屏幕截图以红色显示了两个意外的LB,蓝色显示了两个nginx ingress LB,分别用于我们的qa和prod env。 kubectl的输出获取服务 gcp gke服务视图中错误信息入口的屏幕截图 这是意料之中的

  • 我有两个实体。我想在持久化所有者实体时级联插入子实体,并将子实体的SSO_ID设置为生成器为所有者生成的实体。 ID类是: 相反,我得到了一个错误: 插入hub_users_emails(user_sso_idemail_typesso_idstart_dateuser_mail)值 (?, ?, ?, ?, ?) (等) 绑定参数[1]as[BIGINT]-[1234837655]= (等) 将

  • Q1)以下是我在为MySQL源创建kafka连接器时使用的配置。 为什么会创建cdc.fkw.supply.mp和_ _ debezium-heart beat . CDC . fkw . supply . MP主题? 我在这两个主题中看到了一些垃圾数据。 Q2) 有没有Restapi知道工作服务器上的kafka连接转换器配置?如果没有API,那么我们存储所有工作属性的配置文件的路径是什么? 这是

  • 但我有以下问题: 这是我的docker-compose.yml文件 我的Postgres.DockerFile是