我正在升级实体库以与 Hibernate 6.x 和 Jakarta EE 兼容。在查询继承自连接表实体的类时,出现以下异常。 (类/包名称因原因而被替换):
class com.example.ServiceOrder cannot be cast to class com.example.GoodsOrder (com.example.ServiceOrder and com.example.GoodsOrder are in unnamed module of loader 'app')
示例 SQL 测试:
factory = Persistence.createEntityManagerFactory("order-persistence-unit");
entityManager = factory.createEntityManager();
final var query = entityManager.createQuery("select serviceOrder from com.example.ServiceOrder serviceOrder where serviceOrder.orderId = :orderId", ServiceOrder.class).setParameter("orderId", 1L);
final var serviceOrder = query.getSingleResult();
这些类通过公共超类 Order 继承,并通过 Join 列注释进行映射:
子类
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.PrimaryKeyJoinColumn;
import jakarta.persistence.Table;
@Entity
@Table(name = "SERVICE_ORDER")
@PrimaryKeyJoinColumn(name = "SERVICE_ORDER_ID", referencedColumnName = "ORDER_ID")
public class ServiceOrder extends Order implements Serializable {
private Order order;
@OneToOne(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn
public Order getOrder() { return this.order; }
.....
}
超级班
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import jakarta.persistence.Temporal;
@Entity
@Table( name = "Order" )
@Inheritance(strategy = InheritanceType.JOINED )
public class Order implements Serializable {
private Long orderId;
private GoodsOrder goodsOrder;
private ServiceOrder serviceOrder;
@GenericGenerator(
name = "com.example.OrderIdGenerator",
strategy = "org.hibernate.id.IdentityGenerator")
@Id
@GeneratedValue(generator = "com.example.OrderIdGenerator")
@Column( name = "ORDER_ID", unique = true, nullable = false)
public Long getOrderId() { return this.orderId; }
@OneToOne(fetch = FetchType.LAZY, mappedBy = "order")
public ServiceOrder getServiceOrder() { return this.serviceOrder; }
....
}
尝试使用 ServiceOrder 实例分配 GoodsOrder 类型的字段时,它会正确抛出异常。
对于 Hibernate 5.x 和 javax 类来说,这可以按预期工作。 我在 Hibernate 6 版本中找不到任何参考资料来说明为什么基于注释的属性映射不正确。
----更新----
在简化的项目中进一步测试后,当超类有超过1个子类的字段引用时,就会出现错误。 在上面的示例中,Order 类中有 ServiceOrder 和 GoodsOrder 字段。
在简化的项目中进一步测试后,当超类有超过1个子类的字段引用时,就会出现错误。 在上面的示例中,Order 类中有 ServiceOrder 和 GoodsOrder 字段。
@Entity
@Table( name = "Order" )
@Inheritance(strategy = InheritanceType.JOINED )
public class Order implements Serializable {
private Long orderId;
private GoodsOrder goodsOrder;
private ServiceOrder serviceOrder;
@GenericGenerator(name = "com.example.OrderIdGenerator",
strategy = "org.hibernate.id.IdentityGenerator")
@Id
@GeneratedValue(generator = "com.example.OrderIdGenerator")
@Column( name = "ORDER_ID", unique = true, nullable = false)
public Long getOrderId() { return this.orderId; }
@OneToOne(fetch = FetchType.LAZY, mappedBy = "order")
public ServiceOrder getServiceOrder() { return this.serviceOrder; }
@OneToOne(fetch = FetchType.LAZY, mappedBy = "order")
public GoodsOrder getGoodsOrder() { return this.goodsOrder; }
更多的探索性测试表明,
mappedBy
中的@oneToOne
属性导致Hibernate 6尝试将查询的实例(ServiceOrder
)分配给超级中具有相同mappedBy目标(getGoodsOrder
)的其他字段类。
该库是由 hibernate-tools 对旧数据库进行逆向工程生成的,因此使用相同
mappedBy
值的原因没有记录。
当前的解决方案似乎是删除超类上的一对一注释。