Hibernate Explicit Connection Table

I have an m: n relationship, such as here , except that some information needs to be associated with an AuthorBook object. So, it seems to me that I don’t need @JoinTable at all and should create a class AuthorBook , consisting of one link to each of Author and Book , and additional information, right?

I tried it like

 @Entity public class AuthorBook { @Id @ManyToOne Author author; @Id @ManyToOne Book book; @LobOrWhatever AdditionalInformation additionalInformation; } 

and I ran into problems (I can’t remember anymore). So I entered @GeneratedId int id and changed the links to @NaturalId . This works mostly well, but funny, it forces me to pass the attached Author and Book to Session#byNaturalId , which makes no sense to me (I have identifiers, and entities should be taken together). I also tried

 session.byNaturalId(AuthorBook.class) .using("author.id", someAuthorId) .using("book.id", someBookId) .load(); 

but I was denied that I said that "author.id" is not a natural id (which is actually true since the natural id is an "author", but its "id" works equally well).

Looking at the Internet, I find that everyone uses identifiers instead of entities in such a table, so I wonder if I'm trying something impossible ... (or stupid).

+5
source share
2 answers

UPD: Removed unnecessary @AssociationOverrides . Added @ManyToOne(fetch = FetchType.LAZY) to avoid modifying StackOverflowException on cascade .

I have had a similar problem lately. I found my solution with @EmbededId .

My database has a Rating table that provides a many-to-many relationship between the user and the video, so userId and movieId are foreign keys and form a composite primary key. And this table also contains some additional information.

Here is my code, I hope this helps you:

Film:

 @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; } 

User:

 @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; } 

Rating:

 @Entity @Table(name = "rating") public class Rating { @EmbeddedId private RatingId primaryKey = new RatingId(); @Column(name = "rating_value") private Integer ratingValue; } 

A utility class that implements a composite identifier for a rating:

 @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; } } 
+5
source

You need to create 2 more classes.

@Embeddable @EmbeddedId

If you want, you can skip @AssociationOverrides.

Check out the link below. http://www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/

+3
source

All Articles