我有一个@OneToOne
批注,我想在2个可能的列上加入。我知道如何通过普通的SQL查询来做到这一点,但我不知道如何使用休眠注释。
以下实体:
@Entity
public class Foo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@OneToOne
@JoinColumn(name = "cancelRecord")
private Foo cancelRecord;
private String externalId;
private String externalCancellationId;
}
和相应的数据库表:
create table Foo(
id int identity(1,1) not null primary key, --primary key
cancelRecord int,
externalId varchar(100),
externalCancellationId varchar(100)
)
到目前为止,cancelRecord
仅加入该列。现在,我希望它加入cancelRecord
或externalCancellationId
上。有效的SQL查询为:
SELECT f.*
FROM Foo f
INNER JOIN Foo fo
ON (f.cancelRecord = fo.id
OR f.externalCancellationId = fo.externalId)
此查询的关键部分是连接子句OR
中的 (f.cancelRecord = fo.id **OR** f.externalCancellationId = fo.externalId)
。
我认为@JoinColumn
无法做到这一点,我需要以某种方式依赖@JoinFormula
。
该假设正确吗?如果是这样,我是否只需要将上述查询复制为@JoinFormula
?
我尝试使用此@JoinFoluma
:
@OneToOne
@JoinFormula(value = "SELECT f.*
FROM Foo f
INNER JOIN Foo fo
ON (f.cancelRecord = fo.id
OR f.externalCancellationId = fo.externalId)")
private Foo cancelRecord;
这会在加载spring上下文时导致NullPointerException
:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [spring/test-database.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1589)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:554)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 43 common frames omitted
Caused by: java.lang.NullPointerException: null
at org.hibernate.cfg.AnnotationBinder.bindOneToOne(AnnotationBinder.java:3185)
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1798)
at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:961)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:788)
at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:250)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:231)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:274)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:84)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:474)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:85)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:689)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:724)
at org.springframework.orm.hibernate5.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:511)
at org.springframework.orm.hibernate5.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:495)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1648)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1585)
... 50 common frames omitted
编辑:
使用this question解决了异常,但遗憾的是,它再次以AND
而不是OR
结尾。
答案 0 :(得分:1)
由于@JoinColumn
或@JoinFormula
用于确定外键列值,因此该方法不起作用,因此它们不适用于多个列。
如果定义多个@JoinColumn
或@JoinFormula
,则ON关系将使用AND
而不是OR
。
在您的情况下,由于您可能只想读取此关联,而不是使用Hibernate进行设置,因此最好使用SQL查询。
答案 1 :(得分:-2)
您可以使用多个@JoinColumn
注释。请参见下面的示例:
@OneToOne
@JoinColumns(
{
@JoinColumn(updatable=false,insertable=false, name="cancelRecord", referencedColumnName="cancelRecord"),
@JoinColumn(updatable=false,insertable=false, name="other", referencedColumnName="other")
}
)
private Foo cancelRecord;