Java 带有复合主键的 SELECT 查询

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23480307/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 23:17:55  来源:igfitidea点击:

SELECT query with composite primary key

javasqlhibernatejpa

提问by CodeMed

In a spring mvc app using hibernate and jpa, I recently switched to a composite primary key using an @Embeddableclass. As a result, I need to update the JPA query that returns a given object based on its unique id. The following is the JPA code that used to work, but which no longer returns a result:

在使用 hibernate 和 jpa 的 spring mvc 应用程序中,我最近使用@Embeddable类切换到复合主键。因此,我需要更新根据其唯一 id 返回给定对象的 JPA 查询。以下是曾经可以工作但不再返回结果的 JPA 代码:

@SuppressWarnings("unchecked")
public Concept findConceptById(BigInteger id) {
    Query query = this.em.createQuery("SELECT conc FROM Concept conc WHERE conc.id =:cid");
    query.setParameter("cid", id);
    return (Concept) query.getSingleResult();
}

How do I change the above query so that it returns the Concept with the most recent effectiveTimefor the given id?Note that idand effectiveTimeare the two properties of the ConceptPKcomposite primary key, and that thus the property definitions and getters and setters for idand effectiveTimeare in the ConceptPKclass and NOT in the Conceptclass.

如何更改上述查询,以便它返回effectiveTime给定最新的概念id注意,ideffectiveTime是的两个属性ConceptPK复合主键,并且从而为属性定义和getter和setterideffectiveTime是在ConceptPK类,而不是在Concept类。

The error thrown by the above is:

上面抛出的错误是:

Caused by: java.lang.IllegalArgumentException:  
Parameter value [786787679] did not match expected type [myapp.ConceptPK]  

This is how the primary key is now defined in the Conceptclass:

这是现在在Concept类中定义主键的方式:

private ConceptPK conceptPK;  

And here is the code for the ConceptPKclass:

这是ConceptPK该类的代码:

@Embeddable
class ConceptPK implements Serializable {

    @Column(name="id", nullable=false)
    protected BigInteger id;

    @Column(name="effectiveTime", nullable=false)
    @Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    private DateTime effectiveTime;

    public ConceptPK() {}
    public ConceptPK(BigInteger bint, DateTime dt) {
        this.id = bint;
        this.effectiveTime = dt;
    }

    /** getters and setters **/
    public DateTime getEffectiveTime(){return effectiveTime;}
    public void setEffectiveTime(DateTime ad){effectiveTime=ad;}

    public void setId(BigInteger id) {this.id = id;}
    public BigInteger getId() {return id;}

    @Override
    public boolean equals(Object obj) { 
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        final ConceptPK other = (ConceptPK) obj;
        if (effectiveTime == null) {
            if (other.effectiveTime != null) return false;
            } else if (!effectiveTime.equals(other.effectiveTime)) return false;
        if (id == null) {
            if (other.id != null) return false;
        } else if (!id.equals(other.id)) return false;
        return true;
    }

    @Override
    public int hashCode() { 
        int hash = 3;
        hash = 53 * hash + ((effectiveTime == null) ? 0 : effectiveTime.hashCode());
        hash = 53 * hash + ((id == null) ? 0 : id.hashCode());
        return hash;
    }
}

采纳答案by Alexey Malev

To use parts of composite primary key in JPA query, you have to address them using its variable names:

要在 JPA 查询中使用复合主键的一部分,您必须使用其变量名来寻址它们:

public Concept findConceptById(BigInteger id) {
    Query query = this.em.createQuery("SELECT conc FROM Concept conc WHERE conc.conceptPK.id =:cid order by conc.conceptPK.effectiveTime desc");
    query.setParameter("cid", id);
    return (Concept) query.getSingleResult();
}

I used Conceptas entity name assuming the class with @Entityannotation is also named Concept.

我用作Concept实体名称,假设带@Entity注释的类也被命名为Concept.

This questioncontains information about similar problem, you may find it useful.

此问题包含有关类似问题的信息,您可能会发现它很有用。

回答by Zahid M

Please try this

请试试这个

@SuppressWarnings("unchecked")
public Concept findConceptById(BigInteger id) {
    Query query = this.em.createQuery("from Concept conc WHERE conc.conceptPK.id = :cid order by conc.conceptPK.effectiveTime desc");
    query.setParameter("cid", id);
    return (Concept) query.getSingleResult();
}

Make sure conceptPK has getter and setter methods in Concept class.

确保conceptPK 在Concept 类中有getter 和setter 方法。