我正在使用 Hibernate JPA、EnterpriseDB(PostgresPlus Advanced Server 9.2.1.3) 和 Jboss 7.1.1 Final 并在读取具有复合主键和(一对一)外键链接到另一个实体的实体时收到异常。
我准备了一个项目来展示这个案例。单击此处下载示例项目文件。注意:该文件将在接下来的 7 天内在服务器上可用。如果需要,我可以上传文件并更改链接。
我尝试读取实体列表,将复合主键的列之一与参数匹配。
public List<TableA> getComposites(String key) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<TableA> query = cb.createQuery(TableA.class);
Root<TableA> aEntity = query.from(TableA.class);
aEntity.fetch(TableA_.tableB, JoinType.LEFT);
query.where(cb.equal(aEntity.get(TableA_.id).get(TableAPK_.colA), key));
query.select(aEntity).distinct(true);
try {
return em.createQuery(query).getResultList();
} catch (NoResultException ignore) {
return null;
}
}
例外是:
Caused by: org.hibernate.TypeMismatchException: Provided id of the wrong type for class org.test.hibernate.persistence.entity.TableB. Expected: class org.test.hibernate.persistence.entity.TableBPK, got class org.test.hibernate.persistence.entity.TableAPK
表 A 和表 B 与复合主键(col_a、col_b、col_c)一对一链接,共享相同的列名。表 B 的主键也是表 A 主键的外键。
@Embeddable
public class TableAPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
@Column(name="col_a")
private String colA;
@Column(name="col_b")
private String colB;
@Column(name="col_c")
private String colC;
@Entity
@Table(name="table_a")
public class TableA implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private TableAPK id;
@Column(name="col_ex_d")
private String colExD;
//bi-directional one-to-one association to TableB
@OneToOne(mappedBy="tableA", fetch=FetchType.LAZY)
private TableB tableB;
@Embeddable
public class TableBPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
@Column(name="col_a")
private String colA;
@Column(name="col_b")
private String colB;
@Column(name="col_c")
private String colC;
@Entity
@Table(name="table_b")
public class TableB implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private TableBPK id;
@Column(name="col_ex_d")
private Integer colExD;
@Column(name="col_ex_e")
private String colExE;
@Column(name="col_ex_f")
private Boolean colExF;
//bi-directional one-to-one association to TableA
@OneToOne(fetch=FetchType.LAZY)
@PrimaryKeyJoinColumns({
@PrimaryKeyJoinColumn(name="col_a", referencedColumnName="col_a"),
@PrimaryKeyJoinColumn(name="col_b", referencedColumnName="col_b"),
@PrimaryKeyJoinColumn(name="col_c", referencedColumnName="col_c")
})
private TableA tableA;
如果您想在本地进行测试: Project 有一个 liquibase 配置来创建表,甚至插入示例数据本身 ( composite-persistence/src/main/liquibase
)。您可以检查changelog.xml
文件以创建表和主键和外键。但是我没有在包中包含连接属性文件。如果您想在本地运行该项目,我可以尝试帮助设置环境。要测试,只需在部署后在浏览器上调用 servlet
/composite-web/Composite?myKey=a1
如果您想使用 eclipselink 进行测试,只需激活提供程序和属性composite-persistence/src/resources/META-INF/persistence.xml
(它们被注释掉以使用 Jboss 的默认 JPA 提供程序:Hibernate;您需要在 Jboss 服务器上配置 eclipselink 模块)。顺便说一下,实体的设置与eclipselink一起工作。