I have an Entity that uses an ElementCollection. I had troubles setting everything up but found a solution. Now I want to understand why this was required. This is my entity
@Entity
public class FooEntity {
@EmbeddedId
FooEntityId id;
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "permitted_role", joinColumns = {
@JoinColumn(name = "notification_key", referencedColumnName = "notificationKey"),
@JoinColumn(name = "application_name", referencedColumnName = "applicationName")
})
@Column(name = "role")
private Set<String> permittedRoles;
}
with the embeddable
@Embeddable
public class FooEntityId {
@Column(columnDefinition = "varchar(128)", nullable = false)
private String notificationKey;
@Column(columnDefinition = "varchar(128)", nullable = false)
private String applicationName;
}
why do I have to specify the join column name how it is defined in my database but use the referencedColumnName how it is named in my code? If I use snake case for both I get an error
A '@JoinColumn' references a column named 'notification_key' but the target entity 'com.foo.FooEntity' has no property which maps to this column
You should NOT be referencing the referencedColumn name using the java property/field name according to the JPA specification. The issue is you are using Spring, which is NOT JPA compliant by default, and is interjecting what the column name for your primary key columns will be with Hibernate internals. If it didn't, the primary key columns for your entity, as mandated by the JPA spec, would be "notificationKey" and "applicationName" - the specification defaults the column name to the java property name.
Apparently Hibernate's camel case interceptors for the column naming isn't taking this into account until after validation.
You should be able to test this by adding a column annotation on the pk class and defining the name yourself. Something like "my_custom_pk_column_1" should force you to use "my_custom_pk_column_1" in the join column definition as well, regardless of the Java property name.