JPA Criteria API加入具有多个表的单向多对一实体

时间:2016-09-19 15:02:33

标签: java jpa eclipselink criteria derby

我有以下课程:

@Entity
public class IssueAssignment {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @ManyToOne
    private Assignee assignee;

    @ManyToOne
    private Issue issue;

    public IssueAssignment() {
    }

    public int getId() {
        return id;
    }

    public int getAssigneeId() {
        return getAssignee().getId();
    }

    public int getIssueId() {
        return getIssue().getRowId();
    }

    public Assignee getAssignee() {
        return assignee;
    }

    public void setAssignee(Assignee assignee) {
        this.assignee = assignee;
    }

    public Issue getIssue() {
        return issue;
    }

    public void setIssue(Issue issue) {
        this.issue = issue;
    }
}

@Entity
public class Assignee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String userName;

    public Assignee(String userName) {
        super();
        this.userName = userName;
    }

    public Assignee() {
    }

    public int getId() {
        return id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

@Entity    
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "id", 
"author", "created", "state", "url", "appId" }) })
public class Issue implements Labelable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int rowId;
    private String id;
    private String author;
    private Timestamp created;

    @Basic(fetch = FetchType.LAZY)
    @Lob
    private String body;

    @Basic(fetch = FetchType.LAZY)
    @Lob
    private String title;

    private String state;
    private String url;
    private int appId;
    private String milestone;

    @OneToMany(mappedBy = "issue", cascade = CascadeType.ALL)
    @JoinColumn(name = "issueId")
    private List<IssueLabel> labels = new ArrayList<>();

    @OneToMany(mappedBy = "issue", cascade = CascadeType.ALL)
    @JoinColumn(name = "issueId")
    private List<Participant> participants = new ArrayList<>();

    public Issue() {

    }

    // getters and setters

我想要知道的是编写一个函数,该函数返回分配给具有特定assigneeId的受让人的所有问题。本质上,我想创建以下SQL查询作为Criteria API查询:

SELECT Issue.* from IssueAssignment join Issue on
IssueAssignment.issue_rowId = Issue.rowId where IssueAssignment.assignee_id =
<some number>

这是我到目前为止(改编自http://www.thejavageek.com/2014/04/28/criteria-api-joins/):

public List<Issue> getAllAssignedIssues(int assigneeId) {
    EntityManager em = Persistence.createEntityManagerFactory(persistenceUnitName).
    createEntityManager();
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Issue> query = cb.createQuery(Issue.class);
    Root<IssueAssignment> issueAssignment = query.from(IssueAssignment.class);
    Join<IssueAssignment, Issue> issues = issueAssignment.join(IssueAssignment_.issue);
    query.select(issues);
    List<Issue> resultList = em.createQuery(query).getResultList();
    return resultList;
}

这里的第一个问题是连接似乎不起作用,因为我在Issue表和IssueAssignment表之间获得了交叉连接,而不是在Issue.rowId = IssueAssignment.issue_rowId上的内连接。第二个问题是我不知道如何编写where子句。问题是,IssueAssignment中的assignee_id和issue_rowId的表列是由JPA生成的,所以我不能写

.where(cb.equal(IssueAssignment_.assignee_id, assigneeId));

有没有办法直接使用正确的Assignee实例,所以我可以这样做:

.where(cb.equal(IssueAssignment_.assignee.getId(), assigneeId));

如果没有,似乎我也必须加入受让人。我知道你可以链接如:

ListJoin<Issue, Participant> participants = issues.join(Issue_.participants);

但有没有办法进行连接,结果如下所示?

Join<Assignee, Issue> issues = ...

如果是这种情况,我相信我可以用

获得正确的结果
select(issues).where(cb.equal(Assignee_.id, assigneeId));

0 个答案:

没有答案