首页 > 解决方案 > HashMap 到 Spring JPA 的映射扩展

问题描述

我决定创建以下对象:

public class ScoreMap<T> extends HashMap<T, Double>

我想将它们保存在数据库中:

@ElementCollection(fetch = FetchType.EAGER)
private Map<String, Double> keywords = new ScoreMap<>();

效果很好。一切都按预期保存。


现在,在检索时,我似乎无法在没有 TypeCasting 的情况下返回 ScoreMap:

public ScoreMap<String> getKeywords()
{
    return (ScoreMap<String>)keywords;
}

这样做我得到以下错误:

Servlet.service() for servlet [dispatcherServlet] in context with path [/myApp] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: org.hibernate.collection.internal.PersistentMap cannot be cast to entity.ScoreMap (through reference chain: java.util.ArrayList[0]->entity.Document["document_knowledge"]->entity.DocumentKnowledge_$$_jvst505_2["keywords"])] with root cause
java.lang.ClassCastException: org.hibernate.collection.internal.PersistentMap cannot be cast to entity.ScoreMap

我尝试将ScoreMap更改为:

public class ScoreMap<T> extends HashMap<T, Double> implements Map<T, Double>

结果相同。


我需要返回一个ScoreMap以在那里使用其他方法。

我知道我可以轻松地foreach并重新创建对象,但我希望我可以避免这种情况。

那么对于这种情况,哪种方法最好呢?我只是设计了这个明显错误的东西还是我错过了其他东西?

标签: javaspring-bootoracle11gspring-data-jpaspring-data

解决方案


我建议你另一种方法。代表团

你为什么不直接实现接口并接受另一个实例作为构造函数参数,而不是扩展? HashMap<K, V>Map<K, V>Map

class ScoreMap<T> implements Map<T, Double> {
   private final Map<T, Double> delegate;

   ScoreMap(final Map<T, Double> delegate) {
      this.delegate = delegate;
   }

   ...

   @Override
   public Double get(final Object key) {
      // Apply custom logic, if needed
      return delegate.get(key);
   }

   // And so on...
}

然后,使用 agetter和 asetter

@Entity
@...
class YourEntity {
   ...

   private Map<String, Double> keywords;

   @ElementCollection(fetch = FetchType.EAGER)
   public ScoreMap<String> getKeywords() {
      // This is fine as we know the Map will always be a ScoreMap
      return (ScoreMap<String>) keywords;
   }

   public void setKeywords(final Map<String, Double> keywords) {
      this.keywords = new ScoreMap<>(keywords);
   }
}

正如您所看到的,每次 Hibernate设置Map,您都会将其包装在您的ScoreMap中,并具有额外的自定义逻辑。

为了您的兴趣,HibernatePersistentMap确实实现了该Map接口,因此您的ScoreMap.


休眠文档状态

作为要求,必须将持久集合值字段声明为接口类型(参见示例 7.2,“使用 @OneToMany 和 @JoinColumn 的集合映射”)。实际的接口可能是 java.util.Set、java.util.Collection、java.util.List、java.util.Map、java.util.SortedSet、java.util.SortedMap 或任何你喜欢的东西(“任何你喜欢的东西”意味着您必须编写 org.hibernate.usertype.UserCollectionType 的实现)。

所以我将编辑我上面的例子。
作为最后的手段,你可以看看UserCollectionType


推荐阅读