首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >急切地获取包含其他急切获取集合的实体集合

急切地获取包含其他急切获取集合的实体集合
EN

Stack Overflow用户
提问于 2011-10-27 21:37:49
回答 2查看 1K关注 0票数 1

我被实体和字符串之间的M:N关系卡住了。一个用户可以有多个角色,每个角色可以分配给多个用户。Role只是一个字符串。角色包含在包含两列的表中:roleIdroleName

我已经创建了两个实体,但我完全无法使其工作。第一个实体是用户:

代码语言:javascript
复制
@Entity
@Table(name="appUsers")
public class UserEntity {
    @Id
    private String login;
    private String password;
    @OneToMany(fetch=FetchType.EAGER,mappedBy="user") //we always need to load user's roles
    private Collection<UsersToRoles> roles;
    @Transient
    private Collection<String> roleNames;

    public String getLogin() {
        return login;
    }

    public String getPassword() {
        return password;
    }

    @PostLoad
    void prepareRoleNames() {
        roleNames = new HashSet<String>(roles.size());
        for (UsersToRoles mapping : roles)
            roleNames.add(mapping.getNameOfRole());
    }

    public Collection<String> getRoles() {
        return roleNames;
    }
}

第二个是与连接表关联的实体:

代码语言:javascript
复制
@Entity
@IdClass(UsersToRolesId.class)
public class UsersToRoles {
    @Id
    @SuppressWarnings("unused")
    @Column(name="login")
    private String login;
    @Id
    @SuppressWarnings("unused")
    @Column(name="roleId")
    private int roleId;
    @ElementCollection(fetch=FetchType.EAGER)
    @CollectionTable(name="userRoles", joinColumns={@JoinColumn(name="roleId")})
    private List<String> roleName;
    @ManyToOne
    @JoinColumn(name="login")
    @SuppressWarnings("unused")
    private UserEntity user;

    public String getNameOfRole() {
        if (roleName.isEmpty())
            throw new CommonError("Role name for roleId=" + roleId, AppErrors.ACCESSOR_UNAVAILABLE);
        return roleName.get(0);
    }
}

class UsersToRolesId {
    private String login;
    private int roleId;

    /**
     * Implicit constructor is not public. We have to
     * declare public non-parametric constructor manually.
     */
    public UsersToRolesId() {
    }

    @Override
    public int hashCode() {
        return 17*login.hashCode() + 37*roleId;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof UsersToRolesId))
            return false;
        UsersToRolesId ref = (UsersToRolesId)obj;
        return (this.login.equals(ref.login) && this.roleId == ref.roleId);
    }
}

问题是,roleName集合始终为空。我不能让它工作。当我在@CollectionTable注释中的表名中出现错误时,它仍然可以工作。JPA根本不读取子集合。它使select from user表与表UsersToRoles联接,但缺少到表userRoles的联接。

我能做到吗?我能得到一个包含另一个被急切获取的集合的实体集合吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-10-27 23:29:46

你的映射是完全错误的。UsersToRoles有一个roleId列。因此,它指的是单个角色。它怎么会有角色名称的集合呢?login列在实体中映射两次。此外,对我来说,这看起来像一个简单的连接表,除了roleId和login之外没有任何其他属性,这两个属性分别是用户和角色ID的外键。

您应该有两个实体:UserRole,以及一个使用ManyToMany表作为连接表的UsersToRoles关联。就这样。UsersToRoles表不应该映射为实体:它是一个纯连接表。

票数 1
EN

Stack Overflow用户

发布于 2011-10-27 22:54:41

JPA提供者通常有一个配置属性来表示默认的即时获取深度,即Hibernate的hibernate.max_fetch_depth。当您增加它时,请检查是否可以看到更多内容。

另外,考虑一下你的设计。只有在有限的情况下(性能方面),急切地获取集合的子集可能是一个好主意。当你像那样注释你的实体时,你将在所有的用例中使用急切抓取。也许使用"lazy“会更好,并且只需要显式地使用带有JOIN FETCH子句的查询来获取它?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7916689

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档