Storing a Map<String,String> Using JPA

Storing a MapString,String using JPA

JPA 2.0 supports collections of primitives through the @ElementCollection annotation that you can use in conjunction with the support of java.util.Map collections.
Something like this should work:

@Entity
public class Example {
@Id long id;
// ....
@ElementCollection
@MapKeyColumn(name="name")
@Column(name="value")
@CollectionTable(name="example_attributes", joinColumns=@JoinColumn(name="example_id"))
Map<String, String> attributes = new HashMap<String, String>(); // maps from attribute name to value

}

See also (in the JPA 2.0 specification)

  • 2.6 - Collections of Embeddable Classes and Basic Types
  • 2.7 Map Collections
  • 10.1.11 - ElementCollection Annotation
  • 11.1.29 MapKeyColumn Annotation

how to store a MapString, ListString using JPA

Not really an answer but this is the way I've done it.

I store the second level of collection as a blob.

@Entity
@Table(name = "Profiles_table")
public class Profiles {

@Id
@Column(name = "profile_ID", updatable = false, nullable = false)
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;

@Column(length = 16777210)
private final HashMap<String, Set<String>> AllProfiles;

How do I persist a MapString, MapString, String with JPA?

You could serialize it and store it as blob in one column:

@Lob
HashMap<String, Map<String, String>> someMap = new HashMap<>();
//!!!!it needs to be declared as HashMap not Map as Serializable is required for this field

But it works only if you dont want to run queries against content of the map, as in the DB it is stored of course as a sequence of bytes that DB does not understand.

You cannot have @ElementCollection of @ElementCollection in JPA and that is what you would need to have 2 level of maps.

JPA MapString,String mapping

Does not the following work for you?

@ManyToMany(cascade = CascadeType.ALL)
Map<String,EntityType> entitytMap = new HashMap<String, EntityType>();

EntityType could be any entity type, including a String.

Hibernate persist MapString, String without referencing another tables

According to the specification, you should annotate the map like this:

    @ElementCollection(targetClass = String.class)
@CollectionTable(name = "MAP")
@MapKeyColumn(name="key")
@Column(name="value")
private Map<String, String> map;

So @MapKeyColumn, instead of @MapKey.

This is the way you should annotate the map when its defined as:

private Map<Basic, Basic> map; // (i.e. Map<String, String>)

You use the @MapKey annotation when you have map defined as:

private Map<Basic, Entity> map; // (i.e. Map<String, User>)

And finally, you use @MapKeyEnumerated annotation when you have map defined ad:

private Map<Enumeration, Basic> map; // (i.e. Map<MyEnum, String>)

Adding map values into database using jpa

I think you are using @ElementCollection in a wrong way. If this worked, how would you populate map keys when you read the entity from the database? customerTypes should be in a separate table, take a look at this thread for a solution to a similar problem. Something like this

@ElementCollection
@MapKeyColumn(name="customer_type_key")
@Column(name="customer_type_value")
@CollectionTable(name="customer_types", joinColumns=@JoinColumn(name="customer_id"))
Map<String, String> attributes = new HashMap<String, String>();

UPDATE

Regarding your comment, that you want to have a field in which you would put values from the map in some format. In this case, you don't need customerTypes at all, but you can keep it as @Transient field if you need it for something.

@Transient
Map<String, String> attributes = new HashMap<String, String>();

For most trivial implementation, you can use Map#toString() as value for customerType field.

Servlet:

...
Map<String, String> map = new LinkedHashMap<String, String>();

map.put("customerType.private", "Private");
map.put("customerType.corporate", "Corporate");

Customer customer = new Customer();
customer.setCustomerType(map.toString());
...

customerType's value after this will be {customerType.private=Private, customerType.corporate=Corporate}. You will need some custom logic if you want different format.



Related Topics



Leave a reply



Submit