The key and value column name is redefined when matching java.util.Map with JPA annotations

I look at various ways to annotate maps using Hibernate 4.1.9 and JPA annotations.

If I want to save a map where the key is an attribute of an entity value, then the inscription looks like this:

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

Please note that the above mark does not create a connection table, but Map is returned through the query at runtime, therefore the map is dynamic, and you do not need to add an element to the map in Java so that they return upon request.

Now I want the contents of the Map to reflect what the application added to the Map, rather than performing a dynamic request.

There are 4 varieties of the map that I want to save

  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 NO relationship between the key and the value, and there is no relation to the holding Entity. I should be able to specify the join table name well, as the column names for the key and value.

I 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 The card works fine, and in the generated connection table there are columns DEPARTMENT, VALUE, KEY

The other three cases work the same way you can store data in tables, and in Java, query tables with corresponding keys / values ​​and return the expected results - that is, handle storing objects using @ElementCollection

But the column name is overridden by @Column (name = "value") and @MapKeyColumn (name = "key") are ignored when the key or value is Entity.

I 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 overrides of key column names and values ​​are ignored. Does anyone know a way to enforce these column name overrides.

Thanks in advance...

UPDATE .... Looking at the answer from @wypieprz, I think I know the correct annotation so that you can specify the column names for the value and key when the map is bound by a base with an entity value.

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 inverseJoinColumn, I can specify the column name of the value.

But if the key is Entity, I did not find a way to specify the key column name. According to doc @MapKeyColumn "indicates a mapping for the key column of the map whose map key is the base type"

I'm also not sure about the usage comments when the key is Entity and the value is basic. Using ManyToMany just does not work, and I think that I may have to use ElementCollection, but again I can not find a way to specify the column name.

UPDATE 2 ... Thanks to Peter Haliki for the solution.

In conclusion, to name all 3 columns in 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 that two cases are indicated as an ElementCollection, but two cases where this value is another object must use ManyToMany.

+6
source share
1 answer

I use the object as a key to the map, as shown below. Using the @MapKeyJoinColumn annotation, I could specify the name of the column that is the key to the map. This worked for me on Hibernate, not sure what other JPA implementations would do, but it is definitely worth a try.

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

Source: https://habr.com/ru/post/970613/


All Articles