gpt4 book ai didi

java - EclipseLink JPA 跟踪更改

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:59:20 25 4
gpt4 key购买 nike

我尝试记录我的 JPA 实体的任何更改。出于这个原因,每个实体都继承自一个抽象实体类,该类具有一个 LogEntry 对象列表。

抽象实体类:

@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 列表中。

我尝试了以下解决方案:

  • 直接在实体类中使用回调注解(@PreUpdate、@PrePersist等)或在与AbstractEntity连接的实体监听器中分离
  • 在实体监听器中使用 EclipsLink 的 DescriptorEvent 和相应的回调方法。这是最有希望的试验。在 preUpdate 中,我可以向受影响的对象添加一个新的 LogEntry。添加的 LogEntry 甚至被正确保留,但任何数据库操作都会调用 preUpdate(选择也会导致调用 preUpdate),因此我无法区分已更改的对象和未更改的对象。来自描述符事件、相关查询或 unitOfWork 的提供的变更集在每种情况下都是空的。当前对象和旧对象(由描述符事件提供)的比较恕我直言太复杂了,不是吗?另一方面,在 preUpdateWithChanges 中,我可以轻松检测到已更改的实体,但此时添加 logentry 显然为时已晚。不会保留日志记录。

几乎所有这些试验都使我能够更改受影响实体的属性(如名称或 validTo)。但是没有任何解决方案提供创建新 LogEntry 实例或保留此 LogEntry 实例的机会。我还尝试通过 jndi 查找获取 session bean 的实例以手动保留 LogEntry。 jndi 查找有效,但调用 session bean 的创建或更新方法无效。

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

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 由于各种原因没有选择。

EclipseLink 版本为 2.3.2。

最佳答案

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

您可以在提交之前获取更改并保留您的日志(从 UnitOfWork 获取更改集)。

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

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

event.getSession().insertObject(logEntry);

关于java - EclipseLink JPA 跟踪更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15680171/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com