[英]Parameterized constructor on hibernate entity
TL;博士
有什么方法可以干凈地將一些 arguments 傳遞給休眠實例化的 object 后加載?
我有的
@Entity
public class MyEntity {
@Lob
private String mapAsJson;
@Transient
private Map<Long, Double> map = new HashMap<>();
// Getters, null-checks, and all that. Always keeping these two in sync, or at least before it persists
}
我想要的是
@Entity
public class MyEntity {
@Embedded
private MyEmbedded<Long, Double> embeddedMap = new MyEmbedded<>();
}
@Embeddable
public class MyEmbedded<K, V> {
@Lob
private String mapAsJson;
@Transient
private final Map<K, V> map = new HashMap<>();
@PreUpdate @PrePersist
private void storeAsJson() {
// JsonUtil encapsulates com.fasterxml.jackson.databind.ObjectMapper logic
mapAsJson = JsonUtil.toString(map);
}
@PostLoad
private void loadFromJson() {
map.clear();
if (mapAsJson != null)
// JsonUtil encapsulates com.fasterxml.jackson.databind.ObjectMapper logic
map.putAll(JsonUtil.fromString(mapAsJson, HashMap.class));
}
}
為什么我想要它
只是為了很好地封裝這個工作 map object 的水合作用。 如果我還有 2 個像這樣的其他字段,那將是很多重復的代碼。 當然,這是一個非常具體的示例,但它可以擴展到 map 以外的其他對象。
為什么它不起作用
這個JsonUtil.fromString(mapAsJson, HashMap.class)
基本上是在猜測類型。 它目前返回<String, Integer>
的 map ,但我實際上需要Double
。
可能失敗的解決方案 #1
這當然不起作用,因為 hibernate 不知道我的嵌入式 object 參數是什么。
@Entity
public class MyEntity {
@Embedded
private MyEmbedded<Long, Double> embeddedMap = new MyEmbedded<>(Long.class, Double.class);
}
@Embeddable
public class MyEmbedded<K, V> {
@NotNull
private Class<K> keyClass;
@NotNull
private Class<V> valClass;
protected MyEmbedded() {
}
public MyEmbedded(Class<K> keyClass, Class<V> valClass) {
this.keyClass = keyClass;
this.valClass = valClass;
}
// [...]
@PostLoad
private void loadFromJson() {
map.clear();
if (mapAsJson != null)
// NOTICE THIS DIFFERENT LINE
map.putAll(JsonUtil.fromString(mapAsJson, HashMap.class, keyClass, valClass));
}
}
可能的解決方案#2
@Embeddable
public class MyEmbedded<K, V> {
@NotNull
private Class<K> keyClass;
@NotNull
private Class<V> valClass;
// [...]
// Call this in the entity once, on the embedded. Maybe on @PostLoad?
public MyEmbedded<K, V> init(Class<K> keyClass, Class<V> valClass) {
this.keyClass = keyClass;
this.valClass = valClass;
}
}
由於您進一步指定JsonUtil
是自己的 class,我建議為JsonUtil.fromString
使用以下簽名:
public static <K, V> Map<K, V> fromString(String json, Class<K> keyClass,
Class<V> valueClass, @SuppressWarnings("rawtypes") Class<? extends Map> mapClass) {
// ...
這樣,您返回的 map 將被推斷為正確的類型,並且您可以使用您的“我想要的”變體。 對於委托給該方法的其他不太龐大的訪問,您可以使用不同的命名簽名:
public static <V> Map<V> fromStringLongKey(String json,
Class<V> valueClass, @SuppressWarnings("rawtypes") Class<? extends Map> mapClass) {
return fromString(json, Long.class, valueClass, mapClass);
}
//...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.