Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jpa 获取包含其他急切获取的集合的实体集合_Jpa_Entity Relationship_Fetching Strategy - Fatal编程技术网

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

Jpa 获取包含其他急切获取的集合的实体集合,jpa,entity-relationship,fetching-strategy,Jpa,Entity Relationship,Fetching Strategy,我一直在研究实体和字符串之间的M:N关系。一个用户可以有多个角色,并且每个角色可以分配给多个用户。角色只是一个字符串。角色包含在具有两列的表中:roleId和roleName 我已经创建了两个实体,但我绝对无法让它工作。第一个实体是用户: @Entity @Table(name="appUsers") public class UserEntity { @Id private String login; private String password; @OneT

我一直在研究实体和字符串之间的M:N关系。一个用户可以有多个角色,并且每个角色可以分配给多个用户。角色只是一个字符串。角色包含在具有两列的表中:roleId和roleName

我已经创建了两个实体,但我绝对无法让它工作。第一个实体是用户:

@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;
    }
}
第二个是与连接表关联的实体:

@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用户表与表UsersToRoles联接,但缺少到表userRoles的联接


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

JPA提供程序通常有一个表示默认急切获取深度的配置属性,即hibernate.max_fetch_depth for hibernate。当你增加它时,检查你是否能看到更多


另外,想想你的设计。仅在性能方面有限的情况下,急切地获取集合的子集合可能是个好主意。当您这样注释您的实体时,您将在所有用例中使用即时抓取。也许您最好使用lazy,只使用带有joinfetch子句的查询显式地获取它?

您的映射完全错误。UsersToRoles有一个roleId列。因此,它指的是单个角色。它怎么可能有一组角色名呢?登录列在实体中映射两次。此外,在我看来,这就像一个简单的联接表,除了roleId和login之外没有任何其他属性,它们分别是User和Role的id的外键

您应该有两个实体:User和Role,并使用UsersToRoles表作为连接表,具有多个关联。就这样。UsersToRoles表不应映射为实体:它是一个纯联接表