Hibernate:仅通过id而没有实体类的外键

10

我有一个层级实体,它将自己作为父级引用。我需要仅通过 IDs 而不是通过实体实例进行映射(原因太复杂了不方便解释)。所以我定义了以下实体:

class Item {

    @Id
    private String id;

    @ManyToOne(targetEntity = Item.class)
    @JoinColumn(name = "PARENT_ID", nullable = true)
    private String parentId;

}

这看起来运行良好。外键约束在数据库中被正确创建。但是当我执行以下查询时:

SELECT i FROM Item i WHERE i.parentId = :parentId

我遇到了这个异常(重要部分已加粗):

org.hibernate.PropertyAccessException: 出现IllegalArgumentException调用com.example.dom.Item.id的getter方法 在org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:192)处发生 在org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:346)处获取标识符 在org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4746)处获取标识符 在org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:4465)处判断是否为瞬态对象 在org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:243)处判断是否为瞬态对象 在org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:293)处获取实体标识符 在org.hibernate.type.EntityType.getIdentifier(EntityType.java:537)处获取实体标识符 在org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:174)处设置多对一关系 在org.hibernate.param.NamedParameterSpecification.bind(NamedParameterSpecification.java:67)处绑定参数值 在org.hibernate.loader.hql.QueryLoader.bindParameterValues(QueryLoader.java:616)处绑定参数值 在org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1901)处准备查询语句 在org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1862)处执行查询语句 在org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1839)处执行查询语句 在org.hibernate.loader.Loader.doQuery(Loader.java:910)处执行查询 在org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:355)处执行查询并初始化非延迟加载集合 在org.hibernate.loader.Loader.doList(Loader.java:2554)处返回列表 在org.hibernate.loader.Loader.doList(Loader.java:2540)处返回列表 在org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2370)处忽略查询缓存并返回列表 在org.hibernate.loader.Loader.list(Loader.java:2365)处返回列表 在org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:497)处查询列表 在org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:387)处翻译查询语句并查询列表 在org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:236)处执行查询计划并返回列表 在org.hibernate.internal.SessionImpl.list(SessionImpl.java:1300)处返回列表 在org.hibernate.internal.QueryImpl.list(QueryImpl.java:103)处返回列表 在com.example.dao.ItemDao.findChildrenByParentId(ItemDao.java:43)处查找父ID的子项 在com.example.dao.ItemDao$$FastClassBySpringCGLIB$$51b04ce9.invoke()处调用方法 在org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)处调用方法 在org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)处调用连接点 在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)处继续执行 在org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)处拦截持久化异常并抛出 Caused by: java.lang.IllegalArgumentException: 对象不是声明类的实例 在sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)处发生 在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)处发生 在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)处发生 在java.lang.reflect.Method.invoke(Method.java:597)处发生 在org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:169)处发生 ... 76 more

似乎Hibernate试图将属性parentId视为Item类型而不是String类型进行处理。有什么想法吗?请不要建议我使用延迟加载,因为在我的情况下不可行(再次强调,太复杂了)。

可能是重复问题:Hibernate - 使用外键代替实体 - Sergey Vyacheslavovich Brunov
3个回答

3

关联使用实体引用(在这种情况下需要使用真实对象Item)。如果您想使用普通的ID列,则意味着您不希望Hibernate管理它们,请删除关联注释。


但是我应该如何创建外键约束呢?我可以使用外部 DDL 脚本,但那样很笨拙。 - Jardo
2
没有什么阻止你在数据库中设置一个常量。Hibernate只是为你提供了hbm2ddl的好处。 - leeor

0

尝试定义id列,例如尝试这样做。

@Column(name="id")

-1

根据我理解您的问题,这可能会有用。

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private String id;


@ManyToOne
@JoinColumn(name = "parent_id",nullable = true)
private Item item;

5
这正是我所不想要的。 - Jardo
尝试将连接列部分更改为以下内容: @Column(name = "parent_id") private String parentId; - samith kumarasingha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接