可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
In a Many to Many relation between two table with a Mapping table in between, how can I only load ids for the second entity.
Following is the example to explain what I want to achieve here. Below is a sample schema
create table user( id int PrimaryKey, name text ) create table pages ( id int PrimaryKey, page_name text ) create table user_page ( id_user int, id_page int, PrimaryKey (id_user, id_page) )
Note: there are additional columns in user and page tables which i have not included here for brevity.
User entity:
@Entity @Table(name = "user") public class User { @id @column(name="id") private Integer id; @column(name="name") private String name; ... ... } @Entity @Table(name = "page") public class Page { @id @column(name="id") private Integer id; @column(name="page_name") private String name; ... ... }
What I want to do is add another attribute Set<Integer> pageIds
in User
class and have all page ids mapped for a user in this collection.
How can this be done using Hibernate?
回答1:
In User
class:
@ManyToMany @JoinTable( name="user_page", joinColumns = @JoinColumn(name="id_user"), inverseJoinColumns = @JoinColumn(name="id_page") ) public Set<Page> pages;
You can get the id's by iterating over the returned set. By default collections are lazily (i.e. only ids) loaded.
EDIT: If you don't want to map Page
for some reason, you can use @ElementCollection
like this:
@ElementCollection @CollectionTable(name="user_page", joinColumns=@JoinColumn(name="id_user")) @Column(name="id_page") public Set<Long> pageIds;
回答2:
I encountered a problem with the accepted answer, when I wanted to map both pages
and pageIds
. Hibernate will use both of these fields to make changes to the mapping table when a User
is saved, possibly causing a lot of weird behaviour.
I instead solved this by making pageIds
@Transient
and populating the collection using @PostLoad
:
@ManyToMany @JoinTable( name="user_page", joinColumns = @JoinColumn(name="id_user"), inverseJoinColumns = @JoinColumn(name="id_page") ) public Set<Page> pages; @Transient public Set<Long> pageIds; @PostLoad private void postLoad() { pageIds = pages.stream().map(Page::getId).collect(Collectors.toSet()); }