java - 休眠实体上的参数化构造函数
问题描述
TL;博士
有什么方法可以干净地将一些参数传递给休眠实例化的对象后加载?
我有的
@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));
}
}
为什么我想要它
只是为了很好地封装进出这个工作地图对象的水合作用。如果我还有 2 个像这样的其他字段,那将是很多重复的代码。当然,这是一个非常具体的例子,但它可以扩展到地图以外的其他对象。
为什么它不起作用
这JsonUtil.fromString(mapAsJson, HashMap.class)
基本上是猜测类型。它目前返回的地图<String, Integer>
,但我实际上需要Double
.
可能失败的解决方案 #1
这当然不起作用,因为休眠不知道我的嵌入对象的参数是什么。
@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
是一个自己的类,我建议以下签名JsonUtil.fromString
:
public static <K, V> Map<K, V> fromString(String json, Class<K> keyClass,
Class<V> valueClass, @SuppressWarnings("rawtypes") Class<? extends Map> mapClass) {
// ...
这样,您返回的地图将被推断为正确的类型,并且您可以使用您的“我想要的”变体。对于委托给该方法的其他不太庞大的访问,您可以使用不同的命名签名:
public static <V> Map<V> fromStringLongKey(String json,
Class<V> valueClass, @SuppressWarnings("rawtypes") Class<? extends Map> mapClass) {
return fromString(json, Long.class, valueClass, mapClass);
}
//...
推荐阅读
- jquery - 如何从 contentEditable div 中获取所需的 html
- cypher - Gremlin 查询 - 在边缘上重复条件
- php - php artisan make:auth 脚手架不起作用
- javascript - “INSPINIA”管理主题的活动侧边菜单
- swift - 在标签菜单中推送视图时标签栏消失?
- php - 从数据库中检索列表
- mysql - Connection.query() 返回值不能在函数外重复
- curl - 卷曲的 Cron 作业
- anaconda - 如何安装 hunspell python 包?
- python - python pandas到SQL Server错误重载列