Hi,
I am trying to understand why my implementation works. As a basic setup, I have a OneToMany mapping with each user having multiple authorities:
CREATE TABLE users
(
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL UNIQUE,
password TEXT NOT NULL,
is_enabled BOOLEAN NOT NULL
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
CREATE TABLE user_authorities
(
user_id BIGINT UNSIGNED NOT NULL,
authority VARCHAR(255) NOT NULL,
CONSTRAINT uc_user_id_authority UNIQUE (user_id, authority),
CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES users (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
As an ORM represenation, I have a UserEntity
class
package kbh.qata.storage;
import jakarta.persistence.*;
import java.util.HashSet;
import java.util.Set;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
@Table(name = "users")
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "name")
private String name;
@Column(name = "password")
private String password;
@Column(name = "is_enabled")
private boolean enabled;
@OneToMany(
cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE},
mappedBy = "user",
orphanRemoval = true)
private Set<UserAuthorityEntity> userAuthorities = new HashSet<>();
public void addUserAuthority(UserAuthorityEntity userAuthority) {
this.userAuthorities.add(userAuthority);
userAuthority.setUser(this);
}
}
together with a UserAuthorityEntity
class
package kbh.qata.storage;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
// @IdClass(UserAuthorityId.class)
@Table(name = "user_authorities")
public class UserAuthorityEntity {
@Id
@Column(name = "user_id")
private Long userId;
// @Id
@Column(name = "authority")
private String authority;
@ManyToOne
@MapsId
@JoinColumn(name = "user_id")
private UserEntity user;
}
Now, what bothers me: Why is it enough to have a simply @Id
annotation in the UserAuthorityEntity
class? As can be seen from the SQL statements, this does not suffice as a primary key, since only the user_id
and authority
describe a unique tuple.
As you can see in the commented out section, I tried to setup a UserAuthorityId class to be able to to set both userId
and authority
as a primary key tuple.
However, this approach does not work. When starting the application, calling the AdminInitializer class, Hibernate complains that the userId
of the UserAuthorityEntity
is null
. Which is correct, but why doesn’t Hibernate simply set it as the id
it references to from the users
table? Is Hibernate “confused” about the two @Id
annotations? Do I do something wrong?
Thanky in advance for an support.
pd