【问题标题】:Eclipselink History Policy not working with MySQL Generated id'sEclipselink 历史策略不适用于 MySQL 生成的 id
【发布时间】:2023-03-20 00:19:01
【问题描述】:

我有一个简单的实体对象和历史策略

@Entity
@Customizer(MyHistoryPolicy.class)
@Table(name = "employee")
public class Employee {
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    ... accessor methods
}


public class MyHistoryPolicy implements DescriptorCustomizer {

    public void customize(ClassDescriptor descriptor) {
        String historyTableName = descriptor.getTableName() + "_history";
        HistoryPolicy policy = new HistoryPolicy();
        policy.addHistoryTableName(historyTableName);
        policy.addStartFieldName("start_date");
        policy.addEndFieldName("end_date");
        descriptor.setHistoryPolicy(policy);
    }
}

插入新对象可以正常工作。更新对象会导致 id 设置为零。我从 Eclipselink 看到以下调试日志

UPDATE employee SET name = ? WHERE (id = ?)
    bind => [test name, 2]
UPDATE employee_history SET end_date = ? WHERE ((end_date IS NULL) AND (id = ?))
    bind => [2017-09-27 17:45:25.316, 2]
INSERT INTO employee_history (id, name, start_date) VALUES (?, ?, ?)
    bind => [2, test name, 2017-09-27 17:45:25.316]
SELECT LAST_INSERT_ID()

注意历史表插入后的“SELECT LAST_INSERT_ID()”。历史表没有生成的 id,所以这个查询返回零,这个值被覆盖到对象的 id 字段中。原始ID丢失,这对应用程序来说是有问题的。

有谁知道如何用 MySQL 克服 Eclipselink 中的这个不足?

【问题讨论】:

标签: mysql eclipselink


【解决方案1】:

以防万一有人偶然发现这个问题,我确实开发了一个对我有用的解决方法。这很简单,它只是使用 JPA 侦听器来保存和恢复丢失的 Id。这是我的代码:

@MappedSuperclass
public abstract class EclipseLinkHistoryFix {

    @Transient
    private Long savedId;

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @PreUpdate
    public void saveId() {
        savedId = getId();
    }

    @PostUpdate
    public void restoreId() {
        if (savedId != null) {
            if (id == null || id.longValue() != savedId.longValue()) {
                setId(savedId);
            }
            savedId = null;
        }
    }

    public final Long getId() {
        return id;
    }

    public final void setId(Long id) {
        this.id = id;
    }
}

此 hack 依赖于 EclipseLink 的内部行为,因此在未来的更新中可能无法正常工作。幸运的是,在 v2.6.4 中,在插入历史记录后会调用 PostUpdate 回调,因此效果很好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-17
    • 2012-06-09
    • 1970-01-01
    相关资源
    最近更新 更多