【问题标题】:How to persist a HashMap with hibernate如何使用休眠持久化 HashMap
【发布时间】:2011-01-15 14:40:12
【问题描述】:

您好,我对休眠世界很陌生,似乎遇到了障碍。我需要存储的对象中有一个哈希图。

private Map<String, SentimentFrequencyCounts> modelData = null;

问题是我永远不需要对这张地图进行搜索、排序或做任何事情我只需要将它与对象一起保存并在加载对象时加载它,所以我希望 hibernate 有一些方法可以只需序列化它,然后将其存储在 CLOB 或 BLOB 字段中,但我似乎找不到任何方法来做到这一点。

所以我接下来尝试让hibernate像这样保存它

    @OneToMany(mappedBy="ngram_data", fetch = FetchType.EAGER) 
 @MapKey(name = "attributeName") 
 public Map<String, SentimentFrequencyCounts> getModelData() {
  return modelData;
 }

但这在运行时给了我以下异常 org.hibernate.AnnotationException: Use of @OneToMany or @ManyToMany targeting an unmapped class:

SentimentFrequencyCounts 类是我试图坚持的类的内部类。所以基本上我认为我真的不了解hibernate如何用于hashmap。真的很遗憾,我不能让它序列化并将其集中在一个列中。

提前感谢您的帮助和时间。

【问题讨论】:

  • 你是如何映射SentimentFrequencyCoungs的?它是一个单独的实体吗?复合材料?
  • 我有 SentimentFrequencyCount(它是可序列化的)被标记为 @Embeddable,但我也试图让它成为一个实体,但没有运气

标签: java hibernate hashmap


【解决方案1】:

去掉你现有的注释并用@Lob 注释列表 - 这个specifies that a persistent property or field should be persisted as a large object to a database-supported large object type

如果变量的类型是 Serializable 的子类型,您可以完全省略注释; JPA 关于默认映射的规则规定,可序列化且非原始类型或Embeddable 的类型被序列化并存储在 BLOB 列中。然而,List 是不可序列化的,尽管 ArrayList 是可序列化的。

您可以将@Lob 与@ElementCollection 一起使用,但我不确定结果是什么;我不知道这是否会序列化整个列表,或者创建一个表,其中每个列表元素都单独序列化。无论哪种方式,您都可能不感兴趣。

稍后编辑:当然,作为规范的勤奋的学生会知道,此注释仅适用于可序列化类型的字段,而不是恰好包含可序列化对象的字段>类。因此,要完成这项工作,您将不得不参与恶作剧。我看看你是否可以用一个以交叉类型为界的通用通配符做一些聪明的事情,但我认为你不能。但是,您可以编写一个像这样的小类:

class SerializableInstanceOf<T> implements Serializable {
    public final T instance;

    public SerializableInstanceOf(T instance) {
        Serializable s = (Serializable)instance;
        this.instance = instance;
    }
}

并将其用作列表的持有者 - 实体有一个用@Lob 标记的此类字段,并在其中保留对列表的引用。每次您想使用列表时,都需要通过实例字段,可能是通过实体上的 getList 方法。

它很丑,但它应该让你做你需要做的事情。

【讨论】:

  • 我认为这是一般正确的解决方案,但我得到 java.util.HashMap 无法转换为 java.sql.Blob 异常,HashMap 是可序列化的,因为我的键和值类也是如此,所以我是不知道为什么它不能投射它。但再次感谢指向正确方向的指针
  • @JNR:原来我的回答是错误的。请参阅 EJB 3.0 持久性规范的第 2.1.1 节 - 以“实体的持久性字段或属性可能具有以下类型”开头的段落。该段实际上不允许 Map 类型的字段。您可能需要将其声明为 HashMap。讨厌。我不确定你还能做什么。
  • Eclipselink 可以解决问题。我想知道为什么休眠没有序列化预期行为的对象。
【解决方案2】:
@org.hibernate.annotations.Type(
        type = "org.hibernate.type.SerializableToBlobType", 
        parameters = { @Parameter( name = "classname", value = "java.util.HashMap" ) }
)
public Map<String, SentimentFrequencyCounts> getModelData() {
  return modelData;
}

或者即使在大多数情况下也可以这样做(分布式缓存可能是个问题):

@org.hibernate.annotations.Type( type = "org.hibernate.type.SerializableType" )
public Map<String, SentimentFrequencyCounts> getModelData() {
  return modelData;
}

【讨论】:

  • 我使用了您的第一个选项,它成功了!我也可以保存地图并检索它。第二个不起作用,堆栈跟踪说它找不到 org.hibernate.type.Serializable 即使该类在类路径中。不知道这是怎么回事。 ¯\_(ツ)_/¯
  • 糟糕,那是因为第二个包含错字。应该是org.hibernate.type.SerializableType,而不仅仅是org.hibernate.type.Serializable。我已经在上面修复了。
  • 这个解决方案对我来说完美无缺。第一个例子。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多