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

EclipseLink JPA跟踪更改

东门晓博
2023-03-14

我尝试记录JPA实体的任何更改。因此,每个实体都继承自一个抽象实体类,该类具有日志条目对象列表。

AbstractEntity类:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@EntityListeners(ChangeListener.class)
public abstract class AbstractEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Version
    private Long version;
    @Temporal(TemporalType.DATE)
    private Date validFrom;
    @Temporal(TemporalType.DATE)
    private Date validTo;
    private String name;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "abstractEntity")
    private List<LogEntry> logEntry = new ArrayList<LogEntry>();
    //getter and setter
}

LogEntry类:

@Entity
public class LogEntry extends AbstractEntity {

    @ManyToOne
    @JoinColumn
    protected AbstractEntity abstractEntity;
    @ManyToOne
    @JoinColumn
    protected Person person; // creator or updater
    @Column(updatable=false, insertable=false, columnDefinition="TIMESTAMP DEFAULT   CURRENT_TIMESTAMP")
    @Temporal(TemporalType.TIMESTAMP)
    protected Date changeDate;
    protected String comment;
    //getter and setter
}

我的方法是创建一个新的LogEntry对象,并在实体更新或持久化之前将其添加到实体的LogEntry列表中。

我尝试了以下解决方案:

    几乎所有这些试验都使我能够更改受影响实体的属性(如名称或validTo)。但没有任何解决方案提供创建新LogEntry实例的机会,或者更确切地说,提供持久化此LogEntry实例的机会。我还尝试通过jndi查找获取会话bean的实例,以手动持久化日志条目。jndi查找工作正常,但调用会话bean的create或update方法没有效果。

    我当前的实体侦听器如下所示:

    public class ChangeListener extends DescriptorEventAdapter {
    
        @Override
        public void preUpdate(DescriptorEvent event) {
            AbstractEntity entity = (AbstractEntity) event.getObject();
            if (!(entity instanceof LogEntry)) {
                LogEntry logEntry = new LogEntry();
                logEntry.setPerson(getSessionController().getCurrentUser());
                logEntry.setAbstractEntity(entity);
                entity.getLogEntries().add(logEntry);
            }
        }
    }
    

    由于各种原因,Hibernate Envers没有选择。

    Eclipse Link版本是2.3.2。

    共有3个答案

    杨景山
    2023-03-14

    您可以尝试使用历史记录策略跟踪更改

    EclipseLink为跟踪对数据库所做的所有更改提供了扩展支持。可以在类描述符上配置EclipseLink HistoryPolicy来存储原始对象的镜像表,该镜像表将存储对象在任何时间点的状态。这可用于审核目的,或允许查询过去的时间点,或允许恢复旧数据。

    于正志
    2023-03-14

    暂时我通过比较preUpdate中的当前实体和旧实体来解决这个问题。比较是使用Apache Commons Lang的EqualsBuilder完成的。

    public class ChangeAbstractEntityListener extends DescriptorEventAdapter {
    
        @Override
        public void preUpdate(DescriptorEvent event) {
            AbstractEntity originalEntity = (AbstractEntity) event.getOriginalObject();
            AbstractEntity entity = (AbstractEntity) event.getObject();
    
            if (!EqualsBuilder.reflectionEquals(originalEntity, entity, true)) {
                if (!(entity instanceof LogEntry)) {
                    LogEntry logEntry = new LogEntry();
                    logEntry.setPerson(getSessionController().getCurrentUser());
                    logEntry.setAbstractEntity(entity);
                    entity.getLogEntries().add(logEntry);
                }
            }
        }
        //jndi lookup to get the user object
    }
    
    尹钱青
    2023-03-14

    在提交过程中的事件期间持久化新对象可能很困难。

    您可以在提交和持久化日志之前获取更改(从UnitOfWork获取更改集)。

    看,http://wiki.eclipse.org/EclipseLink/FAQ/JPA#How_to_access_what_changed_in_an_object_or_transaction.3F

    否则,可以从事件内部直接插入和对象。

    event.getSession().insertObject(logEntry);
    
     类似资料:
    • 问题内容: 我的同事在工作中提出了一个我无法回答的问题(由于缺乏经验),该问题与跟踪表中相关字段的变化有关。 想象一下,我们有3个表,每个表20个字段。在此示例中,我们考虑这些表中的每一个都有2个字段,一个名为LastUpdatedOn,另一个名为LastUpdatedBy。 如果我们只想跟踪这3个表中的更改,而只跟踪几个特定字段,而没有为每个表创建包含更新前最新版本的历史表,那么我们如何跟踪这些

    • 跟踪行为控制着 Entity Framework Core 是否会在其变更跟踪器里维持实体实例的信息。如果实体是被跟踪的,任何检测到的该实体的变更都将在 SaveChanges() 时持久化到数据库中。Entity Framework Core 还会对已跟踪的、之前已加载到 DbContext 实例中的查询和实体进行相互的导航属性装配。 提示 你可以在 GitHub 上查阅当前文章涉及的代码样例。

    • 我尝试使用R标记编写所有数据分析报告,因为我可以有一个可复制的文档,可以以多种输出格式(Pdf、html和MS Word)共享。 然而,我的大多数同事都使用MS Word,他们不知道R、Markdown等。 使用R Markdown的一个优点是,我可以在MS Word中生成报告,并直接与同事共享。 缺点是协作对我来说变得很麻烦,因为我也会收到MS Word的反馈(通常使用跟踪更改),并且我必须手动

    • 该项目 为了寻找解决方案,我首先使用maven在执行LiquiBase:Update时将变更日志的SVN修订版存储到中。基于修订版号检索变更日志容易出错。 我已经花了一周的时间来寻找一个健壮的解决方案,在谷歌上搜索了几个小时,构建了几个测试用例(使用了适应的父级和具体的POM,部分使用了maven scm插件等等),但没有运气。最初,我计划使用LiquiBase:tag存储文件路径+修订,但只有当

    • Trace 事件提供了一种机制,可以集中由 V8,Node 核心, 以及用户代码生成的跟踪信息。 启动 Node.js 应用时添加 --trace-events-enabled 标记,可以启用 Tracing. 可以通过在 --trace-event-categories 标记后跟一个用逗号分隔的类别名称列表, 来指定特定的跟踪记录集合。 node 和 v8 默认启用。 node --trace-

    • 跟踪配置指定了Envoy使用的HTTP跟踪器的全局设置。在服务的顶层配置上定义。未来,Envoy可能会支持其他跟踪器,但现在HTTP跟踪器是唯一支持的跟踪器。 { "http": { "driver": "{...}" } } http (optional, object) 提供HTTP跟踪器的配置。 driver (optional, object) 提供处理跟踪和创建span