通过单个列而不是复合主键连接
Join by a single column instead of a composite primary key
我有一个 JPA 实体,我想在此 table 上添加自联接。 Table 看起来像
@Entity
@Table(name = "TABLE_A")
@IdClass(TableAPk.class)
public class TableA implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "COLUMN_1", nullable = false, length = 64)
private String column_1;
@Id
@Column(name = "COLUMN_2", nullable = false, precision = 10, scale = 2)
private BigDecimal column_2;
@ManyToOne
@JoinColumn(name = "COLUMN_1", insertable = false, updatable = false)
//@ManyToOne(optional = true, fetch = FetchType.LAZY)
//@JoinTable(name = "KEY_MAPPING",
// joinColumns = { @JoinColumn(name = "J_COLUMN_1", referencedColumnName = "COLUMN_1", insertable = false, updatable = false) } )
private TableA tableA;
@OneToMany(mappedBy="tableA", fetch = FetchType.LAZY)
private Set<TableA> tableASet;
IdClass 看起来像:
public class TableAPk implements Serializable {
// default serial version id, required for serializable classes.
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;
private String column_1;
private BigDecimal column_2;
根据我的业务逻辑,我只需要在单个列上添加自连接
final Join<TableA, TableA> joinASelf = joinX.join("tableA", JoinType.INNER);
但是table有复合主键,所以@Id注解的字段不止一个。我得到这样的异常:
原因:org.hibernate.AnnotationException:从 com.data.TableA 引用 com.data.TableA 的外键列数错误。应该是 2.
如何在此处仅在单个列上添加自连接?我是 JPA 的新手,所以如果我遗漏了什么,请告诉我。
2015 年 2 月 21 日更新:
我添加了注释 @AssociationOverride 来覆盖关联:
@ManyToOne
@AssociationOverride(name="tableA",
joinColumns=@JoinColumn(name="COLUMN_1"))
private TableA tableA;
生成的列名显示为"TABLE_A_COLUMN_2"。我无法找出原因。有什么线索吗?
- 正确的方法是(不是 OP 想要的)
您可以使用@JoinColumns
注释(注意复数而不是单数),从而加入:
@Entity
@Table(name = "TABLE_A")
@IdClass(TableAPk.class)
public class TableA implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "COLUMN_1", nullable = false, length = 64)
private String column1;
@Id
@Column(name = "COLUMN_2", nullable = false, precision = 10, scale = 2)
private BigDecimal column2;
@ManyToOne
@JoinColumns({
@JoinColumn(name = "FK_COL1", referencedColumnName="COLUMN_1"),
@JoinColumn(name = "FK_COL2", referencedColumnName="COLUMN_2")
})
private TableA tableA;
@OneToMany(mappedBy="tableA", fetch = FetchType.LAZY)
private Set<TableA> tableASet;
- 问题解决方法:
删除 @ManyToOne
/@OneToMany
关系并添加一个 private String refCol1;
。有了它,为 JPQL 编写相应的条件查询:SELECT t1 FROM TableA t1, TableA t2 WHERE t2.refCol1 = t1.column1
使用 CriteriyQuqeries
解决方案如下所示:
final CriteriaBuilder criteriaBuilder = entityManagerMds.getCriteriaBuilder();
// This Pojo is used to fetch only selected fields
final CriteriaQuery<DummyPojo> createQuery = criteriaBuilder.createQuery(DummyPojo.class);
final Root<TableX> tableX = createQuery.from(TableX.class);
final Join<TableX, TableA> joinTableA = tableX.join("tableAs", JoinType.INNER);
// Every time you want to add a self join, create new root
final Root<TableA> tableA = createQuery.from(TableA.class);
final Predicate predicateSelfJoin = criteriaBuilder.equal(joinTableA.<String>get("column_1"), tableA.<String>get("column_1"));
我有一个 JPA 实体,我想在此 table 上添加自联接。 Table 看起来像
@Entity
@Table(name = "TABLE_A")
@IdClass(TableAPk.class)
public class TableA implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "COLUMN_1", nullable = false, length = 64)
private String column_1;
@Id
@Column(name = "COLUMN_2", nullable = false, precision = 10, scale = 2)
private BigDecimal column_2;
@ManyToOne
@JoinColumn(name = "COLUMN_1", insertable = false, updatable = false)
//@ManyToOne(optional = true, fetch = FetchType.LAZY)
//@JoinTable(name = "KEY_MAPPING",
// joinColumns = { @JoinColumn(name = "J_COLUMN_1", referencedColumnName = "COLUMN_1", insertable = false, updatable = false) } )
private TableA tableA;
@OneToMany(mappedBy="tableA", fetch = FetchType.LAZY)
private Set<TableA> tableASet;
IdClass 看起来像:
public class TableAPk implements Serializable {
// default serial version id, required for serializable classes.
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;
private String column_1;
private BigDecimal column_2;
根据我的业务逻辑,我只需要在单个列上添加自连接
final Join<TableA, TableA> joinASelf = joinX.join("tableA", JoinType.INNER);
但是table有复合主键,所以@Id注解的字段不止一个。我得到这样的异常:
原因:org.hibernate.AnnotationException:从 com.data.TableA 引用 com.data.TableA 的外键列数错误。应该是 2.
如何在此处仅在单个列上添加自连接?我是 JPA 的新手,所以如果我遗漏了什么,请告诉我。
2015 年 2 月 21 日更新: 我添加了注释 @AssociationOverride 来覆盖关联:
@ManyToOne
@AssociationOverride(name="tableA",
joinColumns=@JoinColumn(name="COLUMN_1"))
private TableA tableA;
生成的列名显示为"TABLE_A_COLUMN_2"。我无法找出原因。有什么线索吗?
- 正确的方法是(不是 OP 想要的)
您可以使用@JoinColumns
注释(注意复数而不是单数),从而加入:
@Entity
@Table(name = "TABLE_A")
@IdClass(TableAPk.class)
public class TableA implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "COLUMN_1", nullable = false, length = 64)
private String column1;
@Id
@Column(name = "COLUMN_2", nullable = false, precision = 10, scale = 2)
private BigDecimal column2;
@ManyToOne
@JoinColumns({
@JoinColumn(name = "FK_COL1", referencedColumnName="COLUMN_1"),
@JoinColumn(name = "FK_COL2", referencedColumnName="COLUMN_2")
})
private TableA tableA;
@OneToMany(mappedBy="tableA", fetch = FetchType.LAZY)
private Set<TableA> tableASet;
- 问题解决方法:
删除 @ManyToOne
/@OneToMany
关系并添加一个 private String refCol1;
。有了它,为 JPQL 编写相应的条件查询:SELECT t1 FROM TableA t1, TableA t2 WHERE t2.refCol1 = t1.column1
使用 CriteriyQuqeries
解决方案如下所示:
final CriteriaBuilder criteriaBuilder = entityManagerMds.getCriteriaBuilder();
// This Pojo is used to fetch only selected fields
final CriteriaQuery<DummyPojo> createQuery = criteriaBuilder.createQuery(DummyPojo.class);
final Root<TableX> tableX = createQuery.from(TableX.class);
final Join<TableX, TableA> joinTableA = tableX.join("tableAs", JoinType.INNER);
// Every time you want to add a self join, create new root
final Root<TableA> tableA = createQuery.from(TableA.class);
final Predicate predicateSelfJoin = criteriaBuilder.equal(joinTableA.<String>get("column_1"), tableA.<String>get("column_1"));