我目前正在使用以下方案开展项目:
Profile
-------
CODE | CHAR(6)
CODE_FUNCTION | CHAR(2)
Function
--------
CODE | CHAR(2)
此处最重要的部分是从Profile
到Function
(CODE_FUNCTION
=> CODE
)的外键。
但是,并非每个配置文件都有一个功能,因此在某些情况下,CODE_FUNCTION只是一个空行(" "
)。
我使用:
映射了函数(在Profile
中)
@OneToOne
@JoinColumn(name = "CODE_FUNCTION", referencedColumnName = "CODE")
private Function function;
在Function
表中,使用以下代码映射代码:
@Id
@Column(name = "CODE_FUNCTION")
private String code;
当配置文件有一个功能时这是正常工作,但是,当没有输入功能代码时,我收到以下错误:
Caused by: javax.persistence.EntityNotFoundException: Unable to find org.example.entities.Function with id
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$JpaEntityNotFoundDelegate.handleEntityNotFound(EntityManagerFactoryBuilderImpl.java:181)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:218)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:274)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:150)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1070)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:989)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:716)
at org.hibernate.type.EntityType.resolve(EntityType.java:502)
at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:170)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:144)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1114)
at org.hibernate.loader.Loader.processResultSet(Loader.java:972)
at org.hibernate.loader.Loader.doQuery(Loader.java:920)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:324)
at org.hibernate.loader.Loader.loadEntity(Loader.java:2148)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:78)
at org.hibernate.loader.entity.EntityLoader.loadByUniqueKey(EntityLoader.java:161)
at org.hibernate.persister.entity.AbstractEntityPersister.loadByUniqueKey(AbstractEntityPersister.java:2385)
at org.hibernate.type.EntityType.loadByUniqueKey(EntityType.java:767)
at org.hibernate.type.EntityType.resolve(EntityType.java:505)
at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:170)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:144)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1114)
at org.hibernate.loader.Loader.processResultSet(Loader.java:972)
at org.hibernate.loader.Loader.doQuery(Loader.java:920)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354)
at org.hibernate.loader.Loader.doList(Loader.java:2553)
at org.hibernate.loader.Loader.doList(Loader.java:2539)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2369)
at org.hibernate.loader.Loader.list(Loader.java:2364)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:496)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:387)
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:231)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1264)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:103)
at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:573)
at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:449)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:311)
at com.sun.proxy.$Proxy77.getResultList(Unknown Source)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:96)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:61)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:96)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:86)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:337)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
... 92 more
这里的问题(我假设)是因为我们使用的是一个空字符串(而不是NULL`),映射失败了,因为它试图找到具有该ID的函数。
有没有办法在不调整所有表记录并用NULL
替换这些空字符串的情况下防止这种情况发生?
例如,我知道我可以使用实体侦听器来处理某些字段,但是我可以对使用@JoinColumn
注释的字段执行相同操作吗?
答案 0 :(得分:2)
添加@NotFound注释
@OneToOne
@JoinColumn(name = "CODE_FUNCTION", referencedColumnName = "CODE")
@NotFound(action=NotFoundAction.IGNORE)
private Function function;
答案 1 :(得分:1)
如果您只是使用@NotFound(action = NotFoundAction.IGNORE),则强制Hibernate为每个缺少的FK发出额外的SELECT请求。实际上我找到了一个更好的解决方案:使用@JoinFormula。
所以而不是:
@JoinColumn(name = "CODE_FUNCTION", referencedColumnName = "CODE")
使用:
@JoinFormula(name = "NULLIF(CODE_FUNCTION, '')", referencedColumnName = "CODE")
这样,空关系被Hibernate识别为NULLS。