我尝试记录我的JPA实体的任何更改。因此,每个实体都从具有LogEntry对象列表的抽象实体类继承。

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列表中,然后更新或保留实体。

我尝试了以下解决方案:
  • 直接在实体类中使用回调注释(@ PreUpdate,@ PrePersist等),或在与AbstractEntity
  • 连接的实体监听器中分隔
  • 在实体监听器中使用EclipsLink的DescriptorEvent和相应的回调方法。这是最有希望的审判。在preUpdate中,我可以向受影响的对象添加新的LogEntry。所添加的LogEntry甚至可以正确持久保存,但是任何数据库操作都将调用preUpdate(select也将导致调用preUpdate),因此,在已更改的对象和未更改的对象之间我不能有所区别。从描述符事件,相关查询或unitOfWork提供的变更集在每种情况下均为null。恕我直言,当前对象和旧对象(由描述符事件提供)的比较太复杂了,不是吗?
    另一方面,在preUpdateWithChanges中,我可以轻松地检测到已更改的实体,但是现在添加一个logentry似乎为时已晚。登录将不会持续。

  • 几乎所有这些试验都使我能够更改受影响实体的属性(例如name或validTo)。但是,没有任何解决方案提供创建新LogEntry实例或持久保留此LogEntry实例的机会。我还尝试通过jndi查找来获取 session bean的实例,以手动保留LogEntry。 jndi查找有效,但是调用 session 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是没有选择的。

    EclipseLink版本是2.3.2。

    最佳答案

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

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

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

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

    IE。

    event.getSession().insertObject(logEntry);
    

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

    10-12 12:55