简体   繁体   English

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

[英]How to persist a custom map with Hibernate/JPA?

I am trying to persist a sub-classed HashMap in a database using Hibernate and JPA annotations. 我试图使用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

}

This gives me the following exception when trying to store parameters: 尝试存储参数时,这给了我以下异常:

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

When I change the declaration to 当我将声明更改为

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

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

I get the following output: 我得到以下输出:

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

If I change it to 如果我将其更改为

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

everything works fine. 一切正常。

So how can I tell Hibernate about Parameters being a collection? 那么我如何告诉Hibernate Parameters是一个集合呢?

You have to create a class that implements UserCollectionType interface and then provide this class to hibernate to tell that you want to use the custom collection. 您必须创建一个实现UserCollectionType接口的类,然后提供此类以使其休眠以告知您要使用自定义集合。

See these links to understand how you can create custom collections: 请参阅以下链接以了解如何创建自定义集合:

How to map custom collection in JPA? 如何在JPA中映射自定义集合?

Hibernate: Custom Collection Types 休眠:自定义集合类型

This is untested . 这是未经测试的 Perhaps you can try and see if this works: Why not just return a Map<String, String> ? 也许您可以尝试看看是否可行:为什么不只返回Map<String, String>

JPA works using common collection interfaces: List , Set , Map . JPA使用常见的收集接口工作: ListSetMap Thus, if Parameters IS-A Map , you can return it as a Map . 因此,如果Parameters IS-A Map ,则可以将其作为Map返回。

Change: 更改:

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

To: 至:

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

Also, because Hibernate has classes that allows lazy loading, ie, PersistentList , PersistentSet , PersistentMap , etc., you can use composition to return a Parameters of what is returned by Hibernate. 另外,由于Hibernate具有允许延迟加载的类,即PersistentListPersistentSetPersistentMap等,因此您可以使用composition返回由Hibernate返回的Parameters

So, you can essentially customize your method to return the values from the returned Hibernate collection. 因此,您实质上可以自定义方法,以从返回的Hibernate集合返回值。

Something of this effect: 这种效果:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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