我在 Java SE 應用程式中的一個物體類中遇到 EclipseLink 更改跟蹤問題。我正在使用 EclipseLink 3.0.2 和 HyperSQL 2.6.1 提供的 Java 8、JPA 3.0。到目前為止,我一直保持我的實作提供程式獨立,因此切換 JPA 提供程式是一種選擇,盡管不是可取的。
這個特定的物體類有大約 10 個型別的屬性OverriddenValue,每個屬性都是 1. 對特定全域配置值的參考和 2. 一個可選的自定義值的包裝器,它將覆寫全域值(如果存在)。
public class OverriddenValue<T> {
@Nullable
private T customValue;
private final OverridableValue<?, T> globalConfigValue;
[...]
}
此類包含 getter 和 setter 邏輯,這使得將自定義值直接存盤在物體中非常不方便。所以我需要包裝這些自定義值。
OverriddenValue我的物體類中的每一個都@Convert使用唯一的AttributeConverter. 所有這些 AttributeConverters 只回傳 Java -> DB 映射的自定義值,對于 DB -> Java 映射,它們使用正確的全域配置重建物件OverridableValue。這是因為我需要對OverridableValue我沒有實作OverriddenValue的參考的參考@Embeddable——我要么不得不保留全域配置值的 ID,要么使其成為暫時的,我認為這太不方便了。此外,每個OverriddenValue實際上只需要資料庫中的一列來存盤其自定義值或空值,因此@Convert應該可以勝任。
我的問題是 EclipseLink 沒有檢測并保留對這些物件的更改。在該物體的托管實體中,對基本 String 屬性的更改將在下次呼叫時自動檢測并持久化EntityManager#flush,但不會更改 an 的 customValue OverriddenValue,并且資料庫中的這些列將保持原樣。
我查看了 EclipseLink 的更改跟蹤是如何作業的,發現有人說它使用 .hashCode() 和 .equals() 來確定屬性是否已更改。所以我在OverriddenValue課堂上手動實作了這些,但它們一定是錯誤的,因為仍未檢測到更改。
暫時放棄提供者獨立性,我嘗試使用 EclipseLink 的@ChangeTracking注釋標記此物體并將其更改ChangeTrackingType為DEFERRED,但這只會導致已經檢測到的更改被延遲,并且無法檢測到任何新的更改。其他跟蹤型別 (ATTRIBUTE和OBJECT) 要求物體實作一個特定的介面ChangeTracker,這似乎很有幫助,但我不太明白如何使它作業。
我還嘗試在persistence.xml檔案中將屬性“eclipselink.weaving.changetracking”設定為false,以防編織導致問題(我不太了解編織)。沒有運氣。
作為一種可能的解決方法,我可以在應用程式關閉時手動合并此型別的所有物體并強制覆寫資料庫中的值。但我認為這是一種黑客行為,并希望盡可能避免它。我覺得 ORM 提供者應該能夠檢測包裝的屬性更改。有誰知道我可以在哪里嘗試解決這個問題?
編輯:這是轉換器類的所有外觀示例:
@Converter
public class FooConverter implements AttributeConverter<OverriddenValue<Integer>, Integer> {
@Override
default Integer convertToDatabaseColumn(OverriddenValue<Integer> attribute) {
return attribute.getCustomValue();
}
@Override
public OverriddenValue<Integer> convertToEntityAttribute(Integer dbData) {
return Config.GLOBAL_CONFIG_VALUE.override(dbData); // Every converter references a different global variable
}
}
該方法override只是一個OverriddenValue工廠方法。
uj5u.com熱心網友回復:
嘗試將映射標記為可變:
@Entity
public class YourClass {
..
@Convert("yourConverter")
@Mutable
private OverriddenValue value1;
..
}
或者,您可以修改自己的保存方法以克隆和設定 OverriddenValue 實體,當您知道其中有要持久化的更改時。
YourClass instance = em.find(id, YourClass.class);
instance.setValue1(instance.getValue1().clone());
instance.getValue1().setCustomValue(value)
em.commit();
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/432641.html
