I'm trying to map up an existing database schema using Hibernate+JPA annotations.
One of my entities are mapped like this:
@Entity
@Table(name = "users")
public class User implements Serializable {
@Id
private int department;
@Id
private int userId;
...
And another entity, Group:
@Entity
@Table(name = "groups")
public class Group implements Serializable {
@Id
private int department;
@Id
private int groupId;
...
Group and User should have a many-to-many relationship between them, but the issue is that the join table ("user_group") only has columns "DEPARTMENT, USERID, GROUPID" - i.e. the DEPARTMENT column needs to be used in both joinColumns and inverseJoinColumns:
@ManyToMany(cascade = { CascadeType.ALL })
@JoinTable(
name = "user_groups",
joinColumns = { @JoinColumn(name = "department"), @JoinColumn(name = "groupid") },
inverseJoinColumns = {@JoinColumn(name = "department"), @JoinColumn(name = "userid") }
)
private List<User> groupUsers = new ArrayList<>();
which gives a mapping error - "Repeated column in mapping for entity".
However, it looks like this was/is possible using XML, because this exact example exists in the old Hibernate documentation. But I cannot find any evidence that this ever worked using annotations? I tried with @JoinFormula instead of @JoinColumn, but that does not compile. Is it possible?
Okay, I'm pretty sure it's not possible.
I found a promising workaround:
Create an @Embeddable for the "user_group" table:
@Embeddable
public class UserGroupMembership implements Serializable {
@ManyToOne
@JoinColumnsOrFormulas(
value = {
@JoinColumnOrFormula(column = @JoinColumn(referencedColumnName = "userid", name = "userid")),
@JoinColumnOrFormula(formula = @JoinFormula(referencedColumnName = "department", value = "department"))
})
private User user;
public UserGroupMembership(User user) {
this.user = user;
}
public UserGroupMembership() {
}
public User getUser() {
return user;
}
}
The trick is that @ManyToOne allows you to use @JoinColumnsOrFormulas, so one of the join conditions can be a formula, which I doesn't seem to work for @ManyToMany (the @JoinColumnsOrFormulas annotation is ignored as it expects the join columns to be part of the @JoinTable annotation).
The UserGroupMemberships are then mapped as a ElementCollection:
@ElementCollection
@CollectionTable(name = "user_group", joinColumns = {
@JoinColumn(name = "department", referencedColumnName = "department"),
@JoinColumn(name = "groupid", referencedColumnName = "groupid")
})
@OrderColumn(name = "seq", nullable = false)
private List<UserGroupMemberships> groupUsers = new ArrayList<>();
This only works right now for a unidirectional many-to-many relationship.