我们有以下数据模型(不重要的列省略):
TABLE_CONNECTION:
+--+
|ID|
+--+
|1 |
|2 |
+--+
TABLE_ENDPOINT:
+--+------+-------------+
|ID|CON_ID|ENDPOINT_TYPE|
+--+------+-------------+
|1 |1 |FROM |
|2 |1 |TO |
|3 |2 |FROM |
|4 |2 |TO |
+--+------+-------------+
字符串
该模型在Hibernate 3.6.10中的Map方式如下:
@Entity
@Table(name = "TABLE_CONNECTION")
@Immutable
public class Connection {
@Id
@Column(name = "ID", unique = true, nullable = false, precision = 38, scale = 0)
private BigDecimal id;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumnsOrFormulas({
@JoinColumnOrFormula(column = @JoinColumn(name = "ID", referencedColumnName = "CON_ID"))
@JoinColumnOrFormula(formula = @JoinFormula(value = "'FROM'", referencedColumnName = "ENDPOINT_TYPE"))
})
private Endpoint fromEndpoint;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumnsOrFormulas({
@JoinColumnOrFormula(column = @JoinColumn(name = "ID", referencedColumnName = "CON_ID"))
@JoinColumnOrFormula(formula = @JoinFormula(value = "'TO'", referencedColumnName = "ENDPOINT_TYPE"))
})
private Endpoint toEndpoint;
...
}
@Entity
@Table(name = "TABLE_ENDPOINT")
@Immutable
public class Endpoint {
@Id
@Column(name = "ID", unique = true, nullable = false, precision = 38, scale = 0)
private BigDecimal id;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "CON_ID", nullable = false)
private Connection connectionId;
@Column(name = "ENDPOINT_TYPE", length = 4, nullable = false)
@Enumerated(EnumType.STRING)
private EndpointType endpointType;
...
}
enum EndpointType {FROM, TO}
的数据
最近我们把Hibernate迁移到了5.2.18版本,简单调用hibernateTemplate.get(Connection.class, BigDecimal.valueOf(1))
就会抛出异常:
java.lang.ClassCastException: com.our.package.Endpoint cannot be cast to java.math.BigDecimal
at org.hibernate.type.descriptor.java.BigDecimalTypeDescriptor.extractHashCode(BigDecimalTypeDescriptor.java:19)
at org.hibernate.type.AbstractStandardBasicType.getHashCode(AbstractStandardBasicType.java:204)
at org.hibernate.type.AbstractStandardBasicType.getHashCode(AbstractStandardBasicType.java:209)
at org.hibernate.engine.spi.EntityUniqueKey.generateHashCode(EntityUniqueKey.java:67)
at org.hibernate.engine.spi.EntityUniqueKey.<init>(EntityUniqueKey.java:48)
at org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:250)
at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:171)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:128)
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.performTwoPhaseLoad(AbstractRowReader.java:238)
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:209)
at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:133)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86)
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:185)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4121)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:278)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:121)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1240)
at org.hibernate.internal.SessionImpl.access$1900(SessionImpl.java:204)
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.doLoad(SessionImpl.java:2842)
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2816)
at org.hibernate.internal.SessionImpl.get(SessionImpl.java:1076)
at org.springframework.orm.hibernate5.HibernateTemplate.lambda$get$0(HibernateTemplate.java:456)
at org.springframework.orm.hibernate5.HibernateTemplate.doExecute(HibernateTemplate.java:367)
at org.springframework.orm.hibernate5.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:334)
at org.springframework.orm.hibernate5.HibernateTemplate.get(HibernateTemplate.java:451)
at org.springframework.orm.hibernate5.HibernateTemplate.get(HibernateTemplate.java:445)
型
你怎么了?
1条答案
按热度按时间yrwegjxp1#
事实证明,升级版的Hibernate无法通过
@JoinColumnAndFormula
连接实体,其中实体本身是强实体(由自己的ID键标识)。由于实体实际上是弱实体(由(CON_ID, ENDPOINT_TYPE)
元组充分标识),更改为多个@ Id注解列的复合标识符解决了这个问题:字符串
(Also
Connection
类中的@JoinColumnsOrFormulas
是不必要的,因为@JoinColumnsOrFormula
注解是@Repeatable
。)**更新:**替代解决方案(稍后发现):
将
Connection.fromEndpoint
和Connection.toEndpoint
字段上的@OneToOne
注解更改为@ManyToOne
(急切与否无关紧要)。