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 UserAuthorityEntityclass
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