我有 2 个实体,比如 Car 和 Engine(只是示例名称,但逻辑是相同的)。
@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;
...
}
Run Code Online (Sandbox Code Playgroud)
那么,我这样做:
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();
Run Code Online (Sandbox Code Playgroud)
抛出异常:
ERROR [main] (JDBCExceptionReporter.java:234) - No value specified for parameter 1.
WARN [main] (TestContextManager.java:409) - Caught exception while allowing TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener@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]
Run Code Online (Sandbox Code Playgroud)
但是,如果我将 Engine 实体更改为在汽车实例本身上只有 @Id(删除 //1 并将 // 2 更改为 @Id),则它可以工作。
根据 JPA 文档,它应该以相同的方式工作(至少我预期)。
我的环境:PostgreSQL 9, Spring framework 3.1, Hibernate 3.6.8.Final, Tomcat 7 (JPA支持由Spring instrumentation添加)。
更新:我已经尝试过使用 EclipseLink 进行两种映射,并且成功了。所以问题可能出在 Hibernate 的某个地方。仍然不知道如何强制它与 Hibernate 一起使用。
我假设您正在使用基于该引擎类中的复合键的 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;
}
Run Code Online (Sandbox Code Playgroud)
根据您的代码示例。
@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;
...
}
Run Code Online (Sandbox Code Playgroud)
假设您尝试使用关系的父键作为新键
如果依赖实体具有单个主键属性(即关系属性或与关系属性对应的属性)并且父实体的主键是简单主键,则依赖实体的主键是简单主键与父实体类型相同的主键(并且既没有指定 EmbeddedId 也没有指定 IdClass)。在这种情况下,要么(1)关系属性被注释为 Id,要么(2)指定一个单独的 Id 属性并且关系属性被注释为 MapsId(并且未指定 MapsId 注释的 value 元素)。
在这种情况下,您的配置应该如下所示工作,这是使用 hibernate 4.3 测试的

| 归档时间: |
|
| 查看次数: |
2810 次 |
| 最近记录: |