简体   繁体   English

hibernate 实体上的参数化构造函数

[英]Parameterized constructor on hibernate entity

TL;DR TL;博士

Is there any way to cleanly pass some arguments to a hibernate-instantiated object post-load?有什么方法可以干净地将一些 arguments 传递给休眠实例化的 object 后加载?

What I have我有的

@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
}

What I want我想要的是

@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));
    }
}

Why do I want it为什么我想要它

Just to nicely encapsulate the hydration to/from this working map object.只是为了很好地封装这个工作 map object 的水合作用。 If I were to have 2 more other fields like this, it would be a lot of repeated code.如果我还有 2 个像这样的其他字段,那将是很多重复的代码。 This is a very specific example, of course, but it could be extended to other objects other than map.当然,这是一个非常具体的示例,但它可以扩展到 map 以外的其他对象。

Why it doesn't work为什么它不起作用

This JsonUtil.fromString(mapAsJson, HashMap.class) is basically guessing the types.这个JsonUtil.fromString(mapAsJson, HashMap.class)基本上是在猜测类型。 It currently returns a map of <String, Integer> , but I'm actually needing Double .它目前返回<String, Integer>的 map ,但我实际上需要Double

Possible failed solution #1可能失败的解决方案 #1

This of course does not work because hibernate has no idea what my parameters for the embedded object are.这当然不起作用,因为 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));
    }
}

Possible solution #2可能的解决方案#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;
    }
}

Due to you further specifying that JsonUtil is an own class, I would suggest the following signature for JsonUtil.fromString :由于您进一步指定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) {
// ...

This way, your returned map will be inferred with the correct types, and you can use your 'What I want'-variant.这样,您返回的 map 将被推断为正确的类型,并且您可以使用您的“我想要的”变体。 You can have differnent named signatures for other, less bulky access, that delegates to that method:对于委托给该方法的其他不太庞大的访问,您可以使用不同的命名签名:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM