Explicit Hibernate join table

随声附和 提交于 2020-01-03 15:32:26

问题


I'm having an m:n relationsship like here, except for that there's some information be to associated with the AuthorBook entity. So I guess, I need no @JoinTable at all and should create a class AuthorBook consisting of one link to each of Author and Book and the 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 recall exactly anymore). So I've introduced a @GeneratedId int id and changed the references to @NaturalId. This works mostly well, but funnily, it forces me to pass attached Author and Book to Session#byNaturalId which makes no sense to me (I have the ids and the entities should be fetched together). I also tried

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

but this was refused telling me that "author.id" is no natural id (which is actually true as the natural id is "author", but its "id" works equally well).

Looking at the web, I find everyone using ids instead of entities in such a table, so I wonder if I'm trying something impossible.... (or stupid).


回答1:


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

I had similar problem recently. I found my solution with @EmbededId.

In my database there is a table Rating that provides many-to-many relation between User and Movie, so userId and movieId are foreign keys and form a composite primary key. And this table also contains some additional information.

Here my code, I hope it will help you:

Movie:

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

Utility class that implements composite id for 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;
    }
}



回答2:


You need to create 2 more classes.

@Embeddable @EmbeddedId

If you want, you can skip @AssociationOverrides.

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



来源:https://stackoverflow.com/questions/32544344/explicit-hibernate-join-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!