简体   繁体   中英

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.

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?

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.

See these links to understand how you can create custom collections:

How to map custom collection in 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> ?

JPA works using common collection interfaces: List , Set , Map . Thus, if Parameters IS-A Map , you can return it as a 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.

So, you can essentially customize your method to return the values from the returned Hibernate collection.

Something of this effect:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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