我有一个层级实体,它将自己作为父级引用。我需要仅通过 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类型进行处理。有什么想法吗?请不要建议我使用延迟加载,因为在我的情况下不可行(再次强调,太复杂了)。