JPA,如何找到具有复合id的对象?

时间:2014-02-24 05:49:39

标签: jpa intellij-idea find datastore

基于第二种方法answered here我设计了我的JPA课程。

@Entity(name = "SearchKeywordJPA")
@IdClass(SearchKeywordJPA.SearchKeyId.class)
public class SearchKeywordJPA implements Comparable<SearchKeywordJPA> {

    @Id
    private String keyword;
    @Id
    private long date;
    private String userUUID;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        SearchKeywordJPA that = (SearchKeywordJPA) o;

        if (date != that.date) return false;
        if (!keyword.equals(that.keyword)) return false;
        if (!userUUID.equals(that.userUUID)) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = keyword.hashCode();
        result = 31 * result + (int) (date ^ (date >>> 32));
        result = 31 * result + userUUID.hashCode();
        return result;
    }

    @Override
    public String toString() {
        return "SearchKeywordJPA{" +
                "keyword='" + keyword + '\'' +
                ", date=" + date +
                ", userUUID='" + userUUID + '\'' +
                '}';
    }

    public String getKeyword() {
        return keyword;
    }

    public void setKeyword(String keyword) {
        this.keyword = keyword;
    }

    public long getDate() {
        return date;
    }

    public void setDate(long date) {
        this.date = date;
    }

    public String getUserUUID() {
        return userUUID;
    }

    public void setUserUUID(String userUUID) {
        this.userUUID = userUUID;
    }

    @Override
    public int compareTo(SearchKeywordJPA searchRecord) {
        long comparedDate = searchRecord.date;

        if (this.date > comparedDate) {
            return 1;
        } else if (this.date == comparedDate) {
            return 0;
        } else {
            return -1;
        }
    }

    /**********************
     * Key class
     **********************/
    public class SearchKeyId {
        private int id;
        private int version;
    }
}

在我的servlet中,我想检查数据存储并存储我的对象(如果不存在)。

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    ...
            for(SearchKeywordJPA item: applicationList) {
                if(!isRecorded(item))
                    storeRecord(item);
            }

        }

    private boolean isRecorded(SearchKeywordJPA record) {
        EntityManager em = EMF.get().createEntityManager();

        SearchKeywordJPA item = em.find(SearchKeywordJPA.class, record);
        return item != null;

    }

    private void storeRecord(SearchKeywordJPA record) {
        EntityManager em = EMF.get().createEntityManager();

        em.persist(record);
    }

但是,当我运行时,应用程序崩溃并记录

javax.persistence.PersistenceException: org.datanucleus.store.appengine.FatalNucleusUserException: Received a request to find an object of type com.twitterjaya.model.SearchKeywordJPA identified by SearchKeywordJPA{keyword='airasia', date=1335680686149, userUUID='FFFF0000'}.  This is not a valid representation of a primary key for an instance of com.twitterjaya.model.SearchKeywordJPA.

是什么原因?任何建议将不胜感激。感谢

2 个答案:

答案 0 :(得分:0)

您将 IdClass 的实例传递给 em.find ...即SearchKeyId。显然,如果你真的有一个no equals/hashCode/toString/constructor的IdClass,那么你可能会遇到很多问题。这些问题只会通过使用GAE / Datastore的古老插件来增加。

答案 1 :(得分:0)

如果您的密钥是

@Entity(name = "SearchKeywordJPA")
@IdClass(SearchKeywordJPA.SearchKeyId.class)
public class SearchKeywordJPA implements Comparable<SearchKeywordJPA> {
你做错了。

  1. IdClass不需要@IdClass的任何注释只是@Id 注释
  2. 密钥不能是实体。
  3. 需要实现Serializable,不需要比较
  4. 需要覆盖equals和hascode,并且没有arg构造函数
  5. 类密钥需要如下所示。

    public class SearchKeyId implements Serializable {
    
        private String keyword;
    
        private long date;
    

    你的实体我会假设这样的事情。

    @Entity(name = "SearchKeywordJPA")
    @IdClass(SearchKeyId.class)
    public class SearchKeywordJPA {
        @Id
        private String keyword;
        @Id
        private long date;
    
        private String userUUID;
    
    • 只要考虑find方法将使用SearchKey.class来查找 实体。
    • IdClass中的字段需要在实体中包含@Id注释。
    • Key不能单独成为实体。
    • 并非真正需要可比较,因为所有比较都放在IdClass