我正在尝试为旧的数据库架构编写一个hibernate适配器。该模式没有专用的id列,但是使用了大约三列来连接数据。
在某些表上,我需要使用合并。到目前为止,这是我想出的:
关于定义:
COALESCE(NULLIF())
好的,下面是代码:
@Entity @Table(name="CAR") public class Car extends TableEntry implements Serializable { @Id @Column(name="DEP_NR") private int depnr; @Id @Column(name="USER_NAME") @Type(type="TrimmedString") private String username; @ManyToOne(fetch = FetchType.EAGER, targetEntity=CarGroup.class) @JoinColumns(value={ @JoinColumn(name="GROUP_NAME"), @JoinColumn(name="DEP_NR"), @JoinColumn(name="state"), }) private CarGroup group; @OneToMany(fetch=FetchType.EAGER, targetEntity=CarUserElement.class, mappedBy="car") private Set<CarUserElement> elements; } @Entity @Table(name="CAR_GROUP") public class CarGroup extends TableEntry implements Serializable { @Id @Column(name="DEP_NR") private int depnr; @Id @Column(name="GROUP_NAME") @Type(type="TrimmedString") private String group; @ManyToOne(fetch = FetchType.EAGER, targetEntity=Car.class) @JoinColumns(value={ @JoinColumn(name="GROUP_NAME"), @JoinColumn(name="DEP_NR"), @JoinColumn(name="state"), }) private Set<Car> cars; @OneToMany(fetch=FetchType.EAGER, targetEntity=CarGroupElement.class, mappedBy="car") private Set<CarGroupElement> elements; } @MappedSuperclass public class CarElement extends TableEntry { @Id @ManyToOne(fetch = FetchType.EAGER, targetEntity=Element.class) @JoinColumns(value={ @JoinColumn(name="ELEMENT_NAME"), @JoinColumn(name="state"), }) private Element element; } @Entity @Table(name="CAR_TO_ELEMENT") public class CarUserElement extends CarElement { @Id @Column(name="DEFINITION") private char definition; @Id @ManyToOne(fetch = FetchType.LAZY) @JoinColumnsOrFormulas(value = { @JoinColumnOrFormula(formula=@JoinFormula(value="COALESCE(NULLIF(DEP_NR, 0), USR_DEP_NR)", referencedColumnName="DEP_NR")), @JoinColumnOrFormula(column=@JoinColumn(name="FORIGN_ELEMENT", referencedColumnName="USER_NAME")), @JoinColumnOrFormula(column=@JoinColumn(name="STATE", referencedColumnName="STATE")) }) private Car car; } @Entity @Table(name="CAR_TO_ELEMENT") public class CarGroupElement extends CarElement { @Id @Column(name="DEFINITION") private char definition; @Id @ManyToOne(fetch = FetchType.LAZY) @JoinColumnsOrFormulas(value = { @JoinColumnOrFormula(formula=@JoinFormula(value="COALESCE(NULLIF(DEP_NR, 0), USR_DEP_NR)", referencedColumnName="DEP_NR")), @JoinColumnOrFormula(column=@JoinColumn(name="FORIGN_ELEMENT", referencedColumnName="GROUP_NAME")), @JoinColumnOrFormula(column=@JoinColumn(name="STATE", referencedColumnName="STATE")) }) private Car car; }
我尝试了所有可用的hibernate版本(从3.5.1 [带@JoinColumnsOrFormulas]的第一个版本到4.xx),但是我总是收到此错误:
@JoinColumnsOrFormulas
Exception in thread "main" java.lang.ClassCastException: org.hibernate.mapping.Formula cannot be cast to org.hibernate.mapping.Column at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:351) at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1338) at org.hibernate.cfg.annotations.CollectionBinder.bindOneToManySecondPass(CollectionBinder.java:791) at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:719) at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:668) at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:66) at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1597) at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1355) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1737) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1788)
其他hibernate用户似乎也有相同的问题:他们无法在任何版本上使用它,请参见此线程和其他stackoverflow问题:https : //forum.hibernate.org/viewtopic.php? f =1& t =1010559
为了更完整,这是我的TrimmedString类:https ://forum.hibernate.org/viewtopic.php ? p = 2191674 & sid = 049b85950db50a8bd145f9dac49a5f6e#p2191674
提前致谢!
PS:它仅通过一个DEP-NR-Column(即,仅使用@JoinColumns使用DEP_NR 或 USR_DEP_NR)就可以将这三个库伦加入到一起。但是我需要这个coalesce(nullif())。
coalesce(nullif())
暂时,联接公式在Hibernate中非常脆弱。我一直很难让他们正常工作。
通常,对我有用的解决方法是创建数据库视图,以显示适当的列(包括原始表中不存在的外键)。然后,我使用分类Hibernate / JPA映射将实体映射到视图。
有时,使用此类实体时,生成的SQL中会有多余的联接,但是在大多数情况下,数据库会优化此类查询,因此无论如何执行计划都是最佳的。
另一种方法可能是使用@Subselects,这是某种Hibernate视图,但是我希望它们的性能不如经典数据库视图。
@Subselect