如何使用Hibernate / JPA保留自定义地图?

时间:2014-10-09 07:34:15

标签: java hibernate jpa

我正在尝试使用Hibernate和JPA注释在数据库中保留一个子类HashMap

import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MapKeyColumn;
import javax.persistence.Table;

@Entity
@Table(name = "module")
public class Module {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private int id;

    @Column(name = "name")
    private String name;

    @Column(name = "description")
    private String description;

    @Column(name = "version")
    private String version;

    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(name = "module_parameter")
    @MapKeyColumn(name = "key")
    @Column(name = "value")
    private Parameters params = new Parameters();

    // Getters & setters

}

在尝试存储参数时,这会给我以下异常:

org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: Module.params

当我将声明更改为

private Map<String, String> params = new Parameters();

public Parameters getParams() {
    return (Parameters) params;
}

我得到以下输出:

Hibernate: select module0_.id as id1_0_, module0_.description as descript2_0_, module0_.name as name3_0_, module0_.version as version4_0_ from module module0_
Hibernate: select params0_.Module_id as Module_i1_0_0_, params0_.value as value2_1_0_, params0_.key as key3_0_ from module_parameter params0_ where params0_.Module_id=?
Exception in thread "main" java.lang.ClassCastException: org.hibernate.collection.internal.PersistentMap cannot be cast to Parameters

如果我将其更改为

private Map<String, String> params = new HashMap<>();

一切正常。

那么如何告诉Hibernate关于Parameters是一个集合呢?

2 个答案:

答案 0 :(得分:2)

您必须创建一个实现UserCollectionType接口的类,然后将此类提供给hibernate以告知您要使用自定义集合。

请参阅以下链接以了解如何创建自定义集合:

How to map custom collection in JPA?

Hibernate: Custom Collection Types

答案 1 :(得分:0)

这是未经测试的。也许您可以尝试看看这是否有效:为什么不返回Map<String, String>

JPA使用常见的集合界面:ListSetMap。因此,如果Parameters IS-A Map,您可以将其作为Map返回。

变化:

public Parameters getParams() {
    return (Parameters) params;
}

要:

public Map<String, String> getParams() {
    return params;
}

此外,由于Hibernate具有允许延迟加载的类,即PersistentListPersistentSetPersistentMap等,您可以使用合成来返回Parameters什么是Hibernate返回的。

因此,您实际上可以自定义方法以返回返回的Hibernate集合中的值。

这种效果:

public Map<String, String> getParams() {
    return new Parameters(params); //params is injected with Hibernate's PersistentMap.
}