Key & value column name overrides when mapping java.util.Map with JPA annotations

I am looking at the different ways of annotating maps using Hibernate 4.1.9 & JPA annotations.

If I want to store a Map where the key is an attribute of the entity value the mark up looks like this

    @OneToMany(mappedBy = "deptById", targetEntity = com.demo.impls.Employee.class)
    @MapKey(name = "entityId")
    private Map<Long, Employee> employeesById;

Note the above mark up does not create a join table but the Map is returned via a query at run-time, so the Map is dynamic and you do not have to add element into the map in Java for them to be returned by the query.

Now I want the contents of the Map to reflect what the application has added into the Map rather than performing a dynamic query.

There are 4 varieties of Map I want to store

    private Map<String, String> map0;
    private Map<String, Entity> map1;
    private Map<Entity, String> map2;
    private Map<Entity, Entity> map3;

In these cases there is NO relationship between the key & and value nor is there any relationship to the holding Entity. I have to be able to specify the name of the join table was well as the column names for the key & value.

I have tried the following

@Entity
public class Department {
    @ElementCollection
    @CollectionTable(name = "TEST_MAP0")
    @Column(name="value")
    @MapKeyColumn(name="Key")
    private Map<String, String> map0;

    @ElementCollection(targetClass = com.demo.bb.impls.Employee.class)
    @CollectionTable(name = "TEST_MAP1")
    @Column(name="value")
    @MapKeyColumn(name="Key")
    private Map<String, Employee> map1;

    @ElementCollection
    @MapKeyClass(value = com.demo.bb.impls.Employee.class)
    @CollectionTable(name = "TEST_MAP2")
    @Column(name="value")
    @MapKeyColumn(name="Key")
    private Map<Employee, String> map2;

    @ElementCollection(targetClass = com.demo.bb.impls.ParkingSpace.class)
    @MapKeyClass(value = com.demo.bb.impls.Employee.class)
    @CollectionTable(name = "TEST_MAP3")
    @Column(name="value")
    @MapKeyColumn(name="Key")
    private Map<Employee, ParkingSpace> map3;

Case 0 Map works fine & the generated join table has columns DEPARTMENT, VALUE, KEY

The other three cases work in as much as you can store data in the tables & in Java interrogate the tables with the relevant keys/values & get back the expected results - i.e. it does handle storing Entities using @ElementCollection

But the column name overrides using @Column(name="value") & @MapKeyColumn(name="key") are ignored when the key or value is an Entity.

I have tried using @ManyToMany annotations as follows

    @ManyToMany(targetEntity = com.demo.bb.impls.Employee.class)
    @JoinTable(name = "TEST_MAP1_B")
    @Column(name="value")
    @MapKeyColumn(name="Key")
    private Map<String, Employee> map1_B;

    @ManyToMany(targetEntity = com.demo.bb.impls.ParkingSpace.class)
    @MapKeyClass(value = com.demo.bb.impls.Employee.class)
    @JoinTable(name = "TEST_MAP3_B")
    @Column(name="value")
    @MapKeyColumn(name="Key")
    private Map<Employee, ParkingSpace> map3_B;

But again the key & value column names overrides are ignored. Does anybody know of a way to enforce these column name overrides.

Thanks in advance...

UPDATE....After looking at the response from @wypieprz I think I know the correct annotation to allow you to specify column names for the value & the key when the Map is keyed by a basic with an entity value.

By using the following

    @ManyToMany(targetEntity = com.demo.bb.impls.Employee.class)
    @JoinTable(name = "TEST_MAP1", inverseJoinColumns=@JoinColumn(name="VALUE"))
    @MapKeyColumn(name="KEY")
    private Map<String, Employee> map1;

Using the inverseJoinColumn I can specify the value column name.

But If the key is an Entity I have not found a way to specify the key column name. As the doc say @MapKeyColumn "specifies the mapping for the key column of a map whose map key is a basic type"

I am also not sure of the annotations to use when the key is an Entity & the value is a basic. Using ManyToMany just does not work & I think I may have to use ElementCollection but again I cannot find a way to specify the key column name.

UPDATE 2... Thanks to Peter Halicky for a solution.

In summary to name all 3 columns on each of the cases you need to do something like this.

@ElementCollection
@CollectionTable(name = "TEST_MAP0", joinColumns = @JoinColumn(name = "DEPARTMENT"))
@Column(name = "value")
@MapKeyColumn(name = "key")
private Map<String, String> map0;

@ManyToMany(targetEntity = com.hibernate.elephants.Employee.class)
@JoinTable(name = "TEST_MAP1", joinColumns = @JoinColumn(name = "DEPARTMENT"), inverseJoinColumns = @JoinColumn(name = "value"))
@MapKeyColumn(name = "key")
private Map<String, Employee> map1;

@ElementCollection
@CollectionTable(name = "TEST_MAP2", joinColumns = @JoinColumn(name = "DEPARTMENT"))
@MapKeyClass(value = com.hibernate.elephants.Employee.class)
@MapKeyJoinColumn(name = "key")
@Column(name = "value")
private Map<Employee, String> map2;

@ManyToMany(targetEntity = com.hibernate.elephants.ParkingSpace.class)
@JoinTable(name = "TEST_MAP3", joinColumns = @JoinColumn(name = "DEPARTMENT"), inverseJoinColumns = @JoinColumn(name = "value"))
@MapKeyClass(value = com.hibernate.elephants.Employee.class)
@MapKeyJoinColumn(name="key")
private Map<Employee, com.hibernate.elephants.ParkingSpace> map3;

Note two cases are specified as ElementCollection but the two cases where the value is another Entity need to use ManyToMany.

Answers


I'm using an entity as a key to a Map, as below. Using the @MapKeyJoinColumn annotation I could specify the name of the column that is the key of the map. This worked for me on Hibernate, not sure what other JPA implementations will do, but it surely is worth trying.

@ElementCollection
@CollectionTable(name="breed_descriptions", joinColumns={ @JoinColumn(name="breed") })
@Column(name="description")
@MapKeyJoinColumn(name="language")
private Map<Language, String> descriptions = new HashMap<>();

Need Your Help

app.home used in mule ajax connector is not working when mule project is converted to web application

mule mule-studio

In mule, the studio flight reservation example is working when I convert it in web application by using web.xml

Change background color on hover with jquery

javascript jquery css html5 css3

Because I am using variable color for buttons, I need to add it with inline css. The hover color is other variable. I cant add hover selector on inline css so, I must use js. I have try to do it with

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.