我正在尝试为旧的数据库模式编写一个休眠适配器。此模式没有专用的 id 列,但使用大约其他三个列来连接数据。
在某些表上,我需要使用合并。到目前为止,这是我想出的:
关于定义:
- 汽车可以具有由汽车用户或汽车用户组分配的元素。
- 如果 FORIGN_ELEMENT 包含用户名,则定义将为 'u'
- 如果 FORIGN_ELEMENT 包含一个组的名称,则定义将为 'g'
- 这也意味着,一个表 (CAR_TO_ELEMENT) 被滥用来将汽车映射到元素,并将汽车组映射到元素。我定义了一个超类 CarElement 和子类 CarUserElement 和 CarGroupElement。
- state 要么是“活动的”,要么是一个无趣的字符串
- 我在其他地方设置了定义和状态,我们不需要担心这个。
- 在连接表上使用 DEP_NR。如果为零,请使用 USR_DEP_NR。我
COALESCE(NULLIF())
在本机 SQL 中成功地做到了这一点,并希望在 Hibernate 中使用 Pojos 实现同样的目标。
好的,我们来看看代码:
@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;
}
我尝试了所有可用的休眠版本(从 3.5.1 [第一个版本@JoinColumnsOrFormulas
] 到 4.xx),但我总是收到此错误:
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)
其他休眠用户似乎也有同样的问题:他们无法使用任何版本,请参阅此线程和其他 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())
。