Log4j JPAAppender Blob垃圾数据问题改造后报错求解决方案
我之前也碰到过Log4j JPAAppender存大体积Blob垃圾数据的坑,调试了好一阵才搞定,结合你现在遇到的报错问题,给你详细的解决方案:
1. 解决「Entity class does not extend AbstractLogEventWrapperEntity」报错
这个报错的核心是你重写的JPAAppender类里,还保留了原生Log4j的校验逻辑——它要求日志实体类必须继承AbstractLogEventWrapperEntity父类。你有两种解决方式:
方式一:让自定义实体类继承父类
直接修改你的com.log4jtest.demo.logger.JpaLogEntity,让它继承org.apache.logging.log4j.core.appender.db.jpa.AbstractLogEventWrapperEntity:
public class JpaLogEntity extends AbstractLogEventWrapperEntity { // 你的实体字段和自定义逻辑 }
这样就能绕过校验逻辑。同时别忘了保持你之前对wrappedEvent字段的修改:确保它带有@Transient注解,避免被EntityManager持久化(这也是解决Blob垃圾数据的关键)。
方式二:移除校验逻辑,完全自定义实体类
如果你不想依赖Log4j的父类,可以修改你重写的JPAAppender相关类(比如JpaDatabaseManager或者JpaAppender的初始化代码),把这段校验代码删掉:
// 找到类似这样的代码并删除 if (!AbstractLogEventWrapperEntity.class.isAssignableFrom(entityClass)) { throw new IllegalArgumentException("Entity class [" + entityClass.getName() + "] does not extend AbstractLogEventWrapperEntity"); }
之后你可以完全自定义实体类,自己映射LogEvent的各个字段(比如日志级别、消息内容、时间戳等)为普通的Java类型(String、Long、Date等),不需要持有LogEvent对象,从根源避免序列化产生Blob垃圾。
2. 彻底解决Blob垃圾数据的可行方案
结合你已经修改wrappedEvent的思路,这里给你更完善的实现:
- 核心问题:原生
AbstractLogEventWrapperEntity的wrappedEvent虽然加了@Transient,但部分JPA提供者(比如Hibernate)的自动探测机制还是会尝试序列化这个对象,导致生成大体积Blob垃圾。 - 具体修改:
- 给
wrappedEvent字段加上双重忽略注解:除了JPA的@Transient,再加上Hibernate专属的@org.hibernate.annotations.Transient(如果用Hibernate的话),或者@JsonIgnore(如果有JSON序列化场景),彻底阻止序列化。 - 如果你选择完全自定义实体类,不要直接持有
LogEvent对象,而是把LogEvent里的必要字段拆解成简单类型持久化。比如把logEvent.getMessage()存为String,logEvent.getTimeMillis()存为Long,这样完全避免复杂对象的序列化问题。 - 检查JPA配置,关闭可能触发不必要序列化的选项,比如Hibernate的
hibernate.enable_lazy_load_no_trans这类配置,防止框架自动序列化未标记的字段。
- 给
内容的提问来源于stack exchange,提问作者Domingo
相关产品推荐
相关产品推荐

