I have a three SQL tables:
create table users (
id serial primary key,
name text not null unique
);
create table posts (
id serial primary key,
data text not null,
authorId integer not null references users (id)
);
create table ratings (
id serial primary key,
name text not null unique
);
One post can have only one author, so users
<-> posts
relation is already established in normal form (correct me if i am wrong).
Ratings are pre-defined constants like "bad", "good" or "awesome", with (in real case) additional data as rating value, description or other fields i omitted here for brevity.
Next i want to relate ratings to users and posts. Each post may be rated once by each user, and may be rated by multiple users. I came up with the following relation:
create table posts_ratings_users_map (
postId integer not null references posts (id),
ratingId integer not null references ratings (id),
userId integer not null references users (id),
primary key (postId, ratingId, userId)
);
But here is the problem: i can't see a way to integrate it within Hibernate ORM mapping, to get for each of posts list (or set, or any other collection) of pairs of (User,Rating).
Here is how i am trying to map them now:
User.java:
@Entity(name = "users")
public class User {
@Id
@Column(nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(nullable = false)
private String name;
@OneToMany
@JoinColumn(name = "authorId")
private Set<Post> posts = new HashSet<>();
// ...
// getters and setters
// ...
}
Rating.java:
@Entity(name = "ratings")
public class Rating {
@Id
@Column(nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(nullable = false)
private String name;
@ManyToMany(mappedBy = "ratings")
private Set<Post> posts = new HashSet<>();
// ...
// getters and setters
// ...
}
Post.java:
@Entity(name = "posts")
public class Post {
@Id
@Column(nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(nullable = false)
private String data;
@ManyToOne
@JoinColumn(name = "authorId")
private User author;
@ManyToMany
@JoinTable(
name = "posts_ratings_users_map",
joinColumns = { @JoinColumn(name = "ratingId") },
inverseJoinColumns = { @JoinColumn(name = "postId") }
)
private Set<Rating> ratings = new HashSet<>(); // here is the problem. i can relate ratings to this post, but how
// do i relate them with users which assigned their ratings to this
// post ?
// ...
// getters and setters
// ...
}
What needs to be changed in order to relate list of pairs of rating&user to each post?
UPD1
Obvious error: PK for posts_ratings_users_map should be (postId, userId)
(excluding ratingId
), otherwise same user was able to put different ratings on the same post.