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:
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.