2012-07-28 51 views
2

我有2個實體,比如汽車和引擎(只是示例名稱,但邏輯相同)。無法使用@MapsId和@Id進行查詢,但只能使用@Id

@Entity 
public class Car { 
    @Id 
    private Long id; 

    @OneToOne(mappedBy = "car", cascade = Cascade.ALL) 
    private Engine engine; 
    ... 


} 

@Entity 
public class Engine { 
    @Id 
    private Long id; // 1 

    @MapsId // 2 
    @OneToOne 
    @JoinColumn(name = "car_id") // join column is optional here 
    private Car car; 
    ... 
} 

所以,後來我做的:

em.save(car); // successfully saved, data is in the database, but (see below) 
TypedQuery<Engine> query = em.createQuery("select engine from Engine engine where engine.car = :car", Engine.class) 
query.setParameter("car", car); 

query.getResultList(); 

拋出異常:

ERROR [main] (JDBCExceptionReporter.java:234) - No value specified for parameter 1. 
WARN [main] (TestContextManager.java:409) - Caught exception while allowing TestExecutionListener  [org.springframew[email protected]17e5cbd] to process 'after' execution for test: method , exception [org.springframework.orm.jpa.JpaSystemException: org.hibernate.exception.DataException: could not execute query; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.DataException: could not execute query] 

但是,如果我改變引擎的實體只有有@Id對汽車本身的實例(刪除//1並將// 2更改爲@Id)它的工作原理。

根據JPA文檔,它應該以同樣的方式工作(至少我期望)。

我的環境:PostgreSQL 9,Spring框架3.1,Hibernate 3.6.8.Final,Tomcat 7(JPA支持被Spring Instrumentation添加)。

更新: 我已經試過的EclipseLink既映射和它的工作。所以問題可能與Hibernate有關。仍然不知道如何強制它與Hibernate一起工作。

+0

如果刪除JoinColumn會發生什麼?同時擁有JoinColumn和MapsId似乎是矛盾的。第一個說:使用專用列,第二個說:使用與ID相同的列。 – 2012-07-28 06:10:57

+0

什麼都不會發生。這種情況下的JoinColumn是可選的,它用於爲\ @Id字段設置\ @Column。如果錯過了,則默認使用默認的@JoinColumn,因此使用缺省的\ @JoinColumn中的@ @Id的默認列名。我真的覺得這可能是Hibernate中的錯誤,當然,當然,直到有人證明這一點。 – akazlou 2012-07-29 05:14:05

回答

2

我假設您正在使用基於該類的引擎類中的複合鍵的Id。 @MapsId僅用於擁有@EmbeddedId時,如以下示例所示。

如果從屬實體採用嵌入式ID,以代表其主 鍵,對應於該 關係屬性在嵌入式ID的屬性必須是相同的類型的 父實體,並且必須在主鍵由應用於關係屬性的MapsId註釋 指定。

@Embeddable 
public class DependentId { 
    String name; 
    long empPK; // corresponds to PK type of Employee 
} 
@Entity 
public class Dependent { 
    @EmbeddedId DependentId id; 
... 
// id attribute mapped by join column default 
    @MapsId("empPK") // maps empPK attribute of embedded id 
    @ManyToOne Employee emp; 
} 

根據你的代碼示例。

@Embeddable 
    public class NewKey{ 
     private Long id; 
     private Long carId; // corresponds to PK type of Employee 
    } 

@Entity 
public class Car { 
    @Id 
    private Long id; 

    @OneToOne(mappedBy = "car", cascade = Cascade.ALL) 
    private Engine engine; 
} 

@Entity 
public class Engine { 
    @EmbeddedId NewKey id; 

    @MapsId("carId") // 2 
    @OneToOne 
    @JoinColumn(name = "car_id") // join column is optional here 
    private Car car; 
    ... 
} 

假設你試圖使用的關係的父密鑰作爲新的密鑰

如果從屬實體具有單個主鍵屬性(即, 關係屬性或屬性對應到 關係屬性)和父實體的主密鑰是 簡單主鍵,從屬實體的主鍵是相同類型的父實體的(和 既不EmbeddedId也不是 簡單主鍵IdClass是s pecified)。在這種情況下,或者(1) 關係屬性被註釋爲Id,或者(2)指定單獨的Id 屬性並註釋關係屬性 MapsId(以及指定的MapsId註釋的值元素不是 )。

在這種情況下,您的配置應該可以正常工作,您可以在下面看到,使用hibernate 4進行了測試。3

enter image description here