我发现 Hibernate 有一些奇怪的行为。我在两个使用嵌入式复合主键的实体之间有一对多关系。 (是的,我知道数据设计很糟糕,但这是我必须使用的模式)
@Entity
@Table(name = "T_PLACE")
public class Place {
@EmbeddedId
private PlacePK id;
@OneToMany(mappedBy = "place")
private List<Mode> modes;
// getters and setters
}
@Embeddable
public class PlacePK implements Serializable {
@Column(name = "COMPANY")
private String company;
@Column(name = "AREA")
private String area;
@Column(name = "COLOR")
private String color;
// getters and setters
}
@Entity
@Table(name = "T_MODE")
public class Mode {
@EmbeddedId
private ModePK id;
@ManyToOne
@JoinColumns({
@JoinColumn(name = "COMPANY", insertable = false, updatable = false),
@JoinColumn(name = "AREA", insertable = false, updatable = false),
@JoinColumn(name = "COLOR", insertable = false, updatable = false),
})
private Place place;
private String function;
// getters and setters
}
@Embeddable
public class ModePK implements Serializable {
@Column(name = "COMPANY")
private String company;
@Column(name = "AREA")
private String area;
@Column(name = "COLOR")
private String color;
@Column(name = "MODE_ID")
private String color;
// getters and setters
}
但是在查询某个地点的模式时,生成的 HQL 最终会像这样排序
where
company=?
and color=?
and area=?
最终将区域绑定(bind)到第二个 ? 并将颜色绑定(bind)到第三个 ?。
除非我更改 @JoinColumn 的顺序以将颜色放在区域之前,否则它不起作用。
@JoinColumns({
@JoinColumn(name = "COMPANY", insertable = false, updatable = false),
@JoinColumn(name = "COLOR", insertable = false, updatable = false),
@JoinColumn(name = "AREA", insertable = false, updatable = false),
})
所以我的问题是,是什么导致了这种行为?什么决定了 HQL 中 where 子句的顺序?这不是任何问题,因为我已经弄清楚如何让它工作,但我想理解它。
我正在使用 spring-boot-starter-data-jpa:1.5.10-RELEASE,它使用 Hibernate 5。
编辑
这是我生成 HQL 的方式
@Repository
public interface PlaceRepository extends JpaRepository<Place, PlacePK> {}
然后在测试中:
PlacePK placePK = new PlacePK();
placePK.setCompany("Acme");
placePK.setArea("XYZ");
place.PK.setColor("Blue");
Place place = placeRepository.findOne(placePK);
List<Mode> modes = place.getModes(); // ends up being an empty PersistBag until I switch the order of the @JoinColumns
assertNotNull(modes);
请您参考如下方法:
该顺序很重要,因为 Hibernate 根据此顺序构建连接条件。 Hibernate 不知道如何将特定列相互映射(尽管它可以通过命名比较来实现,但是......)。因此,它只需按照您指定的 ID 列的顺序放置它们即可。
要查看差异排序的作用,请打开生成的 SQL 查询的日志记录。您将看到,如果您的顺序与 ID 键的顺序不一致,您的获取查询可能会出现类似
...join PlacePK pk ON pk.COMPANY = m.AREA*emphasized text*
