当 find(Object.Class, {CompositeKey}) 方法的键是组合键时如何找到引用?

How to find the reference when key to the find(Object.Class, {CompositeKey}) method is a composite key?

当我们有复合键(两列或更多列)作为第二个参数传递给 JPA 时如何找到引用 entityManager.find(Object.class, compositeKey)?

我的尝试- 我创建了一个 Arraylist 并添加了形成 compositeKey 的值,然后将此列表传递给 find 方法。

例如:在我的情况下,useridprojectid 一起是 UserProject table 的关键,这两个已添加到名为 list 的数组列表中,它将作为第二个参数传递给 entityManager find 方法,如下所示:

List<Integer> list = new ArrayList<Integer>();
        list.add(userProjectDO.getUserid());
        list.add(userProjectDO.getProjectid());

        UserProject userProject = em.find(UserProject.class,list);

但这总是 return 为空,即使 userid 和 projectId 存在于 table 上。有没有人遇到过类似的问题?解决方案?

例如 JPA 的 EntityManager#find doesn't accept arrays as key but Object. Since you are talking about composite key you should implement your key in a separate class which will represent the composite key by listing all the key separate properties. You can achieve this using EmbeddedId

例如:

您应该定义复合键 class 并用 @Embeddable 注释:

public class UserProjectKey implements Serializable{
    private String userId;
    private String projectId;

    //constructors, getters, setters
}

并在您的实体中将其用作 @EmbeddedId

要按键搜索,您可以这样做:

UserProjectKey key = new UserProjectKey("userIdExample", "projectIdExample");
em.find(UserProject.class, key);

我找到了另一种方法,即编写 namedQuery 来搜索 table。发布实施以防万一它对任何人都有帮助。

final Query query = em.createNamedQuery("UserProject.findByAll");

用户项目实体class:

@Entity
@Table(name = "userproject", schema = "public")

@NamedQueries({ @NamedQuery(name = "UserProject.findByAll", query = "SELECT a FROM UserProject a where a.userid = :userid and a.projectid = :projectid"),
        @NamedQuery(name = "UserProject.findByUserId", query = "SELECT a FROM UserProject a where a.userid = :userid"),
        @NamedQuery(name = "UserProject.findById", query = "SELECT a FROM UserProject a where a.id = :id" )})
public class UserProject implements Serializable {
    private static final long serialVersionUID = 1L;


    @Id @GeneratedValue(strategy= GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

    @Column(name = "userid")
    private Integer userid;

    @Column(name = "projectid")
    private Integer projectid;

    @Column(name = "created")
    private Timestamp created;

    @Column(name = "modified")
    private Timestamp modified;

    @Column(name = "modifiedbyid")
    private Integer modifiedbyid;

    @Column(name = "role")
    private String role;

    public Integer getId() {
        return id;
    }

    public void setId(final Integer id) {
        this.id = id;
    }

    public Integer getUserid() {
        return userid;
    }

    public void setUserid(final Integer userid) {
        this.userid = userid;
    }


    public void setProjectid(final Integer projectid) {
        this.projectid = projectid;
    }

    public Timestamp getCreated() {
        return created;
    }

    public void setCreated(final Timestamp created) {
        this.created = created;
    }

    public Timestamp getModified() {
        return modified;
    }

    public void setModified(final Timestamp modified) {
        this.modified = modified;
    }

    public Integer getModifiedbyid() {
        return modifiedbyid;
    }

    public void setModifiedbyid(final Integer modifiedbyid) {
        this.modifiedbyid = modifiedbyid;
    }

    public String getRole() {
        return role;
    }

    public void setRole(final String role) {
        this.role = role;
    }
}

最后设置查询参数,即 compositeKey values(userid,projectid) 为:

final Query query = em.createNamedQuery("UserProject.findByAll");
        query.setParameter("userid",userProjectDO.getUserid());
        query.setParameter("projectid",userProjectDO.getProjectid());
        List<UserProject> userProjectList = query.getResultList();

userProjectList 将包含与 compositeKey (userId,projectId)

匹配的行

我看到这种方法的一个优点是我可以根据 need/requirement 在实体 class 中编写 N 个命名查询。例如:如果我们需要处理由此 table 创建的视图。它可以通过首先创建视图然后编写另一个命名查询来处理它来轻松实现。