Hibernate和@JoinFormula:org.hibernate.mapping.Formula无法强制转换为org.hibernate.mapping.Column

我正在尝试为旧的数据库模式编写一个hibernate适配器。 此架构没有专用的id列,但使用大约三个其他列来连接数据。

在某些表格中,我需要使用合并。 这是我到目前为止提出的:

关于定义:

  • 汽车可以具有由汽车用户或汽车的用户组分配的元件。
  • 如果FORIGN_ELEMENT包含用户名,则定义为’u’
  • 如果FORIGN_ELEMENT包含组的名称,则定义为’g’
  • 这也意味着,一个表(CAR_TO_ELEMENT)被误用于将汽车映射到元素和汽车组到元素。 我定义了一个超类CarElement和子类CarUserElement和CarGroupElement。
  • state是“active”或无趣的字符串
  • 我在其他地方设定了定义和陈述,我们不需要担心这一点。
  • 在连接表上使用DEP_NR。 如果为零,请使用USR_DEP_NR。 我在本机SQL中成功地使用COALESCE(NULLIF())并且希望在Hibernate中使用Pojos实现相同的function。

好的,我们在这里使用代码:

 @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 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 cars; @OneToMany(fetch=FetchType.EAGER, targetEntity=CarGroupElement.class, mappedBy="car") private Set 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),但我总是得到这个错误:

 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)就可以加入这三个colulmns。 但我需要这个coalesce(nullif())

暂时加入公式在Hibernate中非常脆弱; 我总是很难让他们正常工作。

经常帮助我的解决方法是创建数据库视图,这些视图暴露了正确的列(包括原始表中不存在的外键)。 然后我使用Hibernate / JPA映射分类将实体映射到视图。

有时在使用此类实体时生成的SQL中存在冗余连接,但数据库在大多数情况下会优化此类查询,以便执行计划无论如何都是最佳的。

另一种方法可能是使用@Subselect ,它是某种Hibernate视图,但我希望它们的性能低于经典的数据库视图。

我遇到了类似的问题,似乎问题是你在@Id中使用@Formula。 Hibernate希望Ids可以插入,而Formulas是只读的。

在我的情况下,我能够通过自己创建单独的列Id属性并使连接对象成为单独的属性来解决该问题。 我不知道这是否适用于您的情况,因为您在公式中使用了两个不同的列,但如果是这样,您的代码可能如下所示:

 @Entity @Table(name="CAR_TO_ELEMENT") public class CarUserElement extends CarElement { @Id @Column(name="DEFINITION") private char definition; @Id @Column(name="DEP_NR") private Integer depNr; @Id @Column(name="USR_DEP_NR") private Integer usrDepNr; @Id @Column(name="FORIGN_ELEMENT") private String userName; @Id @Column(name="STATE") private String state; @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", insertable = false, updatable = false)), @JoinColumnOrFormula(column=@JoinColumn(name="STATE", referencedColumnName="STATE", insertable = false, updatable = false)) }) private Car car; } 

我也遇到了强制转换exception,我正在使用Hibernate 5.x.

直到Hibernate花时间来解决这个问题,我发现虽然这个人的方法可能不是最干净的(他甚至可以避免这个事实!),但它确实有效。

您只需要将@Column映射(和get / set方法)添加到返回null的关联表对象中,并在填充关系数据时手动设置值。 简单但有效!

在此处输入图像描述