我有一个m:n关系,如here,除了有一些信息要与AuthorBook
实体相关联。所以我想,我根本不需要@JoinTable
,应该创建一个class AuthorBook
,其中包含一个指向Author
和Book
的链接以及其他信息,对吗?
我尝试过像
@Entity
public class AuthorBook {
@Id @ManyToOne Author author;
@Id @ManyToOne Book book;
@LobOrWhatever AdditionalInformation additionalInformation;
}
我遇到了问题(我不记得了)。所以我引入了@GeneratedId int id
并更改了对@NaturalId
的引用。这很有效,但有趣的是,它迫使我将附件Author
和Book
传递给Session#byNaturalId
这对我没有意义(我有ids,实体应该一起取出) 。我也试过
session.byNaturalId(AuthorBook.class)
.using("author.id", someAuthorId)
.using("book.id", someBookId)
.load();
但是这被拒绝告诉我“author.id”不是自然的id(实际上这是真的,因为自然id是“作者”,但它的“id”同样有效。)
在网上看,我发现每个人都在这样的表中使用id而不是实体,所以我想知道我是不是想尝试一些不可能的东西......(或者是愚蠢的)。
答案 0 :(得分:5)
UPD:删除了不必要的@AssociationOverrides
。添加了@ManyToOne(fetch = FetchType.LAZY)
以避免在StackOverflowException
次修改时cascade
。
我最近遇到过类似的问题。
我找到了@EmbededId
的解决方案。
在我的数据库中有一个表Rating,它提供User和Movie之间的多对多关系,因此userId和movieId是外键并形成复合主键。此表还包含一些其他信息。
这是我的代码,我希望它会对你有所帮助:
电影:
@Entity
@Table(name = "movie")
public class Movie {
@Id
@Column(name = "movie_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "primaryKey.movie")
private List<Rating> ratings;
}
用户:
@Entity
@Table(name = "imdb_user")
public class User {
@Id
@Column(name = "imdb_user_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "primaryKey.user")
private List<Rating> ratings;
}
评分:
@Entity
@Table(name = "rating")
public class Rating {
@EmbeddedId
private RatingId primaryKey = new RatingId();
@Column(name = "rating_value")
private Integer ratingValue;
}
实现评级的复合ID的实用程序类:
@Embeddable
public class RatingId implements Serializable{
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "movie_id")
private Movie movie;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "imdb_user_id")
private User user;
/*Generated by IDEA*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RatingId ratingId = (RatingId) o;
if (movie != null ? !movie.equals(ratingId.movie) : ratingId.movie != null) return false;
return !(user != null ? !user.equals(ratingId.user) : ratingId.user != null);
}
@Override
public int hashCode() {
int result = movie != null ? movie.hashCode() : 0;
result = 31 * result + (user != null ? user.hashCode() : 0);
return result;
}
}