我正在使用Hibernate JPA,EnterpriseDB(PostgresPlus Advanced Server 9.2.1.3)和Jboss 7.1.1 Final并在读取具有复合主键和(一对一)外键链接到另一个实体的实体时收到异常
我准备了一个展示案例的项目。单击here以下载示例项目文件。 注意:该文件将在接下来的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一起使用。
答案 0 :(得分:0)
由于TableAPK
和TableBPK
相等(具有完全相同的结构),您可以删除一个并在任何地方使用另一个。
我的意思是:删除TableBPK
,重命名TableAPK
执行TablePK
并在任何地方使用它。
像TableA
那样:
@Entity
@Table(name="table_a")
public class TableA implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private TablePK id; //<- this line changed from TableAPK to TablePK
...
TableB
:
@Entity
@Table(name="table_b")
public class TableB implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private TablePK id; //<- this line changed from TableBPK to TablePK