簡體   English   中英

JPQL / HQL:選擇或失敗

[英]JPQL/HQL: select with OR fails

我的查詢有一些問題,但不知道確切的位置。
該查詢返回例如3個Change對象:

select c from Change c where c.entityOne.serial = 'TEST3'

該查詢返回例如2個Change對象:

select c from Change c where c.entityTwo.serial = 'TEST3'

但是當我期望3到5之間的值時,此查詢返回0。

select c from Change c where (c.entityOne.serial = 'TEST3' or c.entityTwo.serial = 'TEST3')

我哪里錯了? 如果您需要更多代碼,請詢問。

進行測試:
很抱歉,有很多代碼,但是重現此問題是必需的。

Change.java

@Entity
public class Change {
    private long id;
    private EntityOne entityOne;
    private EntityTwo entityTwo;

    @Id
    @GeneratedValue
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    @ManyToOne
    public EntityOne getEntityOne() {
        return entityOne;
    }

    public void setEntityOne(EntityOne entityOne) {
        this.entityOne = entityOne;
    }

    @ManyToOne
    public EntityTwo getEntityTwo() {
        return entityTwo;
    }

    public void setEntityTwo(EntityTwo entityTwo) {
        this.entityTwo = entityTwo;
    }
}

EntityOne.java和EntityTwo.java(僅重命名該類)

@Entity
public class EntityOne {
    private long id;
    private String serial;

    @Id
    @GeneratedValue
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getSerial() {
        return serial;
    }

    public void setSerial(String serial) {
        this.serial = serial;
    }
}

Test.java-運行它。

public class Test {
    private static EntityManagerFactory buildFactory() {
        try {
            return Persistence.createEntityManagerFactory("migration-tool");
        } catch (Throwable ex) {
            ex.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        EntityManagerFactory emf = buildFactory();
        EntityManager em = emf.createEntityManager();
        Query q = em.createQuery("select c from Change c where (c.entityOne.serial = 'TEST3' or c.entityTwo.serial = 'TEST3')");
        List<Change> changeRecords =  q.getResultList();
        System.out.println(changeRecords.size());
        emf.close();
    }
}

persistence.xml中

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">
    <persistence-unit name="migration-tool" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>test.Change</class>
        <class>test.EntityOne</class>
        <class>test.EntityTwo</class>
        <properties>
            <property name="hibernate.search.autoregister_listeners" value="false"/>
            <property name="hibernate.cache.region.factory_class"
                      value="net.sf.ehcache.hibernate.EhCacheRegionFactory"/>
            <property name="hibernate.cache.use_query_cache" value="true"/>
            <property name="hibernate.connection.url" value="jdbc:postgresql://127.0.0.1:5434/test"/>
            <property name="hibernate.connection.username" value="postgres"/>
            <property name="hibernate.connection.password" value="123456"/>
            <property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
        </properties>
    </persistence-unit>
</persistence>

pom.xml中的依賴項

<dependency>
    <groupId>postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>9.1-901.jdbc4</version>
</dependency>
<dependency>
    <groupId>javax.persistence</groupId>
    <artifactId>persistence-api</artifactId>
    <version>1.0</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-annotations</artifactId>
    <version>3.4.0.GA</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>3.4.0.GA</version>
</dependency>
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache-core</artifactId>
    <version>2.6.0</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.4.2</version>
</dependency>

和SQL腳本一起填寫數據。

CREATE TABLE entityone
(
  id bigint NOT NULL,
  serial character varying(255),
  PRIMARY KEY (id)
);

CREATE TABLE entitytwo
(
  id bigint NOT NULL,
  serial character varying(255),
  PRIMARY KEY (id)
);

CREATE TABLE change
(
  id bigint NOT NULL,
  entityone_id bigint,
  entitytwo_id bigint,
  PRIMARY KEY (id),
  FOREIGN KEY (entityone_id) REFERENCES entityone(id),
  FOREIGN KEY (entitytwo_id) REFERENCES entitytwo(id)
);

insert into entityone values (1, 'TEST3');
insert into entityone values (2, 'TEST1');
insert into entityone values (3, 'TEST2');
insert into entityone values (4, 'TEST3');

insert into entitytwo values (1, 'TEST3');
insert into entitytwo values (2, 'TEST3');
insert into entitytwo values (3, 'TEST4');
insert into entitytwo values (4, 'TEST3');

insert into change values (1, 1, NULL);
insert into change values (2, 2, NULL);
insert into change values (3, 3, NULL);
insert into change values (4, 4, NULL);
insert into change values (5, NULL, 1);
insert into change values (6, NULL, 2);
insert into change values (7, NULL, 3);
insert into change values (8, NULL, 4);

用評論寫出答案:

問題是NULL值。 Hibernate文檔(v 4.3)的第16.4章規定:

16.4。 連接語法的形式

HQL支持兩種形式的關聯連接:隱式和顯式。

上一節中顯示的查詢全部使用顯式形式,即在from子句中顯式使用join關鍵字。 這是推薦的形式。

隱式形式不使用join關鍵字。 而是使用點符號“取消引用”關聯。 隱式聯接可以出現在任何HQL子句中。 隱式聯接會在結果SQL語句中進行內部聯接

來自Cat,作為cat,其中cat.mate.name類似於'%s%'

我已經加粗了最相關的部分。 這說明您的點表示法將被展開到內部聯接中,並且由於鍵為空-您的實體將不會出現在聯接中。
Hibernate執行的SQL也顯示了這一點(為了便於閱讀,下面將其美化):

select change  
from Change change, EntityOne entityone, EntityTwo entitytwo
where 
change.entityOne_id=entityone.id and
change.entityTwo_id=entitytwo.id and  
(
    ((change.entityOne_id is not null) and entityone.serial='TEST3') or 
    ((change.entityTwo_id is not null) and entitytwo.serial='TEST3')
)

不幸的是,點符號不能使您獲得理想的結果。 您必須自己創建聯接,如上面的文檔第16.3章中所述。 例:

SELECT c
FROM Change AS c
    LEFT JOIN Change.entityOne as entityOne
    LEFT JOIN Change.entityTwo as entityTwo
WHERE
    entityOne.serial = "TEST3" OR entityTwo.serial = "TEST3"

注意:我沒有Hibernate的有效安裝程序,您可能必須在上面添加額外的null檢查

暫無
暫無

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

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