0

DB tables (not quite SQL but you get the gist..)

definition (
  id int, -- PK
  type int,
  label varchar(20) -- definition label can change over time
)

asset (
  id int, -- PK
  -- other asset fields...
)

property (
  id int, -- PK
  asset_id int,      -- with FK to asset + on delete cascade
  definition_id int, -- with FK to definition + on delete cascade
  payload varchar(256)
)

A map of the definition id int to payload (Map<int,String>), like this below, works but that's not what I want.

[Asset class]
@ElementCollection
@CollectionTable(name = "properties", 
  joinColumns = {@JoinColumn(name = "asset_id", referencedColumnName = "id")})
@MapKeyColumn(name = "definition_id")
@Column(name = "payload")
Map<Integer,String> properties;

Instead, I'm trying to have the following map in my Asset class:

Map<Definition,String> properties;

but can't figure what to do. The @MapKeyJoinColumn annotation is intended to pull a relation out of the a entity-type map value so I cannot complete this below:

@OneToMany(cascade = CascadeType.ALL)
@JoinTable(name = "properties", 
  joinColumns = {@JoinColumn(name = "asset_id", referencedColumnName = "id")},
  //inexistant - inverseJoinColumns = {@JoinColumn(name = "property_id", referencedColumnName = "id")})
@MapKeyJoinColumn(name = "definition_id")
Map<Definition,String> properties;

I want a value-type map value. My 'properties' table has the definition_id so I really just need jpa/hibernate to join a table for the entity key, not the value.

Any clue?

user2023577
  • 1,752
  • 1
  • 12
  • 23
  • I am afraid this is impossible. As you want map value to be a `String` you are limited with `@ElementCollection` choice and as `asset` does not have relation with `definition` you can not make map key - `Definition`. – SternK Mar 20 '21 at 09:34
  • 1
    Have you tried `@ElementCollection` with `@MapKeyJoinColumn(name = "definition_id")`? – crizzis Mar 21 '21 at 16:54

1 Answers1

0

From a commenter, this works:

[Asset class]
@ElementCollection
@CollectionTable(name = "properties", 
  joinColumns = {@JoinColumn(name = "asset_id", referencedColumnName = "id")})
@MapKeyJoinColumn(name = "definition_id")
@Column(name = "payload")
Map<Definition,String> properties;

The non-intuitive answer was to force @MapKeyJoinColumn and the key Entity type, regardless of the @ElementCollection presence.

I have no idea if this is just a fluke with hibernate abilities, or if it is actually supported by JPA.

user2023577
  • 1,752
  • 1
  • 12
  • 23
  • Using `@MapKeyJoinColumn` should work with both, `@ElementCollection` and `@OneToMany` or `@ManyToMany`. The mapping looks right to me. – Christian Beikov Mar 23 '21 at 08:03