33

How can I map a Map in JPA without using Hibernate's classes?

4 Answers 4

38

Although answer given by Subhendu Mahanta is correct. But @CollectionOfElements is deprecated. You can use @ElementCollection instead:

@ElementCollection
@JoinTable(name="ATTRIBUTE_VALUE_RANGE", joinColumns=@JoinColumn(name="ID"))
@MapKeyColumn (name="RANGE_ID")
@Column(name="VALUE")
private Map<String, String> attributeValueRange = new HashMap<String, String>();

There is no need to create a separate Entity class for the Map field. It will be done automatically.

Sign up to request clarification or add additional context in comments.

Comments

16

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.

8 Comments

I'm a little confused. The question was about mapping a Map<String, String>, but the "best answer" is about a Map<String, EntityType>. Do i miss something?
EntityType could be any entity type, including a String.
How many tables does this generate? Is there (1) one for the original class, (2) a join table (with keys for the original class and the entity type) and (3) another table for the EntityType (in the given scenario, a table with just the join table key and the mapped string)? This may be a lot of overhead, depending on the Strings saved...
@ChrisKaminski You are wrong for saying that String is entity type because it does not have Id. You know what I mean and you may know what is called entity.
For String,String mapping this will not work along. Suggesting to deselect as best answer.
|
10

Suppose I have an entity named Book which is having a Map of chapters:

import java.io.Serializable;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;    
import org.hibernate.annotations.CollectionOfElements;
import org.hibernate.annotations.MapKey;
@Entity
public class Book implements Serializable{
@Column(name="BOOK_ID")
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long bookId;    

@CollectionOfElements(targetElement=java.lang.String.class)
@JoinTable(name="BOOK_CHAPTER",
        joinColumns=@JoinColumn(name="BOOK_ID"))
@MapKey (columns=@Column(name="CHAPTER_KEY"))
@Column(name="CHAPTER")
private Map<String,String> chapters;
public Long getBookId() {
    return bookId;
}
public void setBookId(Long bookId) {
    this.bookId = bookId;
}
public Map<String,String> getChapters() {
    return chapters;
}
public void setChapters(Map<String,String> chapters) {
    this.chapters = chapters;
}               

}

It works for me.

3 Comments

+1. And what if i want to retrieve only the chapter 3 of all of these books? I have a similar question: stackoverflow.com/questions/12952625/…
@ianaz select c from Book b join b.chapters c where key(c) = '3'
Unfortunately, this requires hibernate-specific annotations. The question was for a solution without.
4

A working example:

@ElementCollection(fetch=FetchType.EAGER)
@CollectionTable(name = "TABLENAME")
@MapKeyColumn(name = "KEY")
@Column(name = "VALUE")
public Map<String, String> getMap() {
    return _map;
}

1 Comment

for a many-to-many relationship, you'd also need joinColumns = @JoinColumn(name="referencing_column") within @CollectionTable and @MapKeyJoinColumn(name="referencing_column_other_table")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.