簡體   English   中英

Hibernate @OneToOne在連接子句中使用OR進行自我連接

[英]Hibernate @OneToOne self join with OR in join clause

我有一個@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僅連接到該列。 現在,我希望它加入cancelRecordexternalCancellationId 一個有效的SQL查詢將是:

SELECT f.* 
FROM Foo f 
        INNER JOIN Foo fo 
        ON (f.cancelRecord = fo.id 
        OR f.externalCancellationId = fo.externalId)

關於此查詢的關鍵部分是join子句中的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

編輯:

這個問題解決了異常,但可悲的是,它再次以AND而不是OR

由於@JoinColumn@JoinFormula用於確定外鍵列值,因此該方法不起作用,因此它們不適用於多個列。

如果定義多個@JoinColumn@JoinFormula ,則ON關系將使用AND而不是OR

在您的情況下,由於您可能只想讀取此關聯,而不是使用Hibernate進行設置,因此最好使用SQL查詢。

您可以使用多個@JoinColumn批注。 請參閱以下示例:

   @OneToOne
   @JoinColumns(
     {
       @JoinColumn(updatable=false,insertable=false, name="cancelRecord", referencedColumnName="cancelRecord"),
       @JoinColumn(updatable=false,insertable=false, name="other", referencedColumnName="other")
     }
   )
   private Foo cancelRecord;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM