2010-05-28 81 views
9

我有兩個類,Test2和Test3。 Test2有一個屬性test3,它是Test3的一個實例。換句話說,我有一個單向OneToOne關聯,test2引用了test3。休眠noob獲取連接問題

當我從db中選擇Test2時,我可以看到正在做一個單獨的選擇來獲取關聯的test3類的詳細信息。這是着名的1 + N選擇問題。

爲了解決這個問題使用單一的選擇,我想使用fetch =加入註解,我的理解是@Fetch(FetchMode.JOIN)語句

然而,取指令集的加入,我還是見單獨的選擇。下面是我設置的相關部分..

的hibernate.cfg.xml:

<property name="max_fetch_depth">2</property> 

的Test2:

public class Test2 { 
@OneToOne (cascade=CascadeType.ALL , fetch=FetchType.EAGER) 
@JoinColumn (name="test3_id") 
@Fetch(FetchMode.JOIN) 
public Test3 getTest3() { 
    return test3; 
} 

NB我設置FetchType爲EAGER出於絕望,即使它無論如何,OneToOne映射默認爲EAGER,但它沒有區別。

感謝您的幫助!

編輯:我幾乎已經放棄嘗試使用FetchMode.JOIN - 任何人都可以確認他們已經得到它的工作,即產生一個左外連接? 在文檔中我看到:「通常,映射文檔不用於自定義提取,而是保留默認行爲,並使用HQL中的左連接提取替代特定事務。」

如果我確實代替左連接取指:

query = session.createQuery(「from Test2 t2 left join fetch t2.test3」);

然後我確實得到了我想要的結果 - 即查詢中的左外連接。

編輯號2:

,大家好,非常感謝你爲你的答覆。現在我想深究這一點。我通常會發現,當我調查一些事情時,我最終會比我想象的要多得多。

我已經學會了一件事 - 我在舊版的hibernate上運行,因爲我沒有意識到maven存儲庫已過時。現在我已經連接到jboss存儲庫了,並且在兩種情況下,我都有最新版本的hibernate和hibernate註釋 - 3.5.1-Final。

我已經設置了一個小測試用例,儘可能簡化它 - 我仍然在3.5中看到這個問題。1 - 決賽,我'99%肯定這只是一些愚蠢的我沒有設置正確,尤其是羅斯,因爲你得到它的工作(謝謝花時間嘗試順便說一句)

所以我有這些類(全文這段時間)

A類

package com.play.hibernate2; 

import javax.persistence.CascadeType; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import javax.persistence.OneToOne; 

import org.hibernate.annotations.Fetch; 
import org.hibernate.annotations.FetchMode; 

@Entity 
public class A { 

    private Integer id; 
    private B b; 

    public A() { 
     super(); 
    } 

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

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

    @OneToOne (cascade=CascadeType.ALL) 
    @Fetch(FetchMode.JOIN) 
    public B getB() { 
     return b; 
    } 

    public void setB(B b) { 
     this.b = b; 
    } 
} 

B類

package com.play.hibernate2; 

import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 

@Entity 
public class B { 

    private Integer id; 

    public B() { 
     super(); 
    } 

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

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

我的整個的hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?> 
<!DOCTYPE hibernate-configuration PUBLIC 
     "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
     "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 

<hibernate-configuration> 

    <session-factory> 

     <!-- Database connection settings --> 
     <property name="connection.driver_class">com.mysql.jdbc.Driver</property> 
     <!-- <property name="connection.driver_class">com.p6spy.engine.spy.P6SpyDriver</property> --> 
     <property name="connection.url">jdbc:mysql://localhost:3306/play</property> 
     <property name="connection.username">play</property> 
     <property name="connection.password">play</property> 

     <!-- JDBC connection pool (use the built-in) --> 
     <property name="connection.pool_size">1</property> 

     <!-- SQL dialect --> 
     <property name="dialect">org.hibernate.dialect.MySQLDialect</property> 

     <!-- Enable Hibernate's automatic session context management --> 
     <property name="current_session_context_class">thread</property> 

     <!-- Disable the second-level cache --> 
     <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> 

     <!-- Echo all executed SQL to stdout --> 
     <property name="show_sql">true</property> 
     <property name="generate_statistics">true</property> 
     <!-- 
     <property name="cache.use_structured_entries">true</property> 
     <property name="cache.use_query_cache">true</property> 
     --> 
     <property name="format_sql">true</property> 
     <property name="use_sql_comments">true</property> 

     <!-- I think this may fix my individual requests for OneToOne problem --> 
     <property name="max_fetch_depth">2</property> 
     <!-- <property name="default_batch_fetch_size">10</property> --> 

    </session-factory>  

</hibernate-configuration> 

測試類

package com.play.hibernate2; 

import java.util.List; 
import java.util.Map; 


import org.hibernate.FlushMode; 
import org.hibernate.Query; 
import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.hibernate.cfg.AnnotationConfiguration; 
import org.hibernate.tool.hbm2ddl.SchemaExport; 

public class RunTests4 { 
    private SessionFactory sessionFactory; 

    public static void main(String[] args){ 
     RunTests4 d = new RunTests4(); 
     d.run3(); 
    } 
    public void run3(){ 

     Session session = getSession(); 
     session.beginTransaction(); 

     createEntities(session); 

     session.getTransaction().commit(); 

     System.out.println("NOW WITH A NEW TRANSACTION"); 
     session = getSession(); 
     session.beginTransaction(); 

     Query query = session.createQuery("from A"); 
     List results = query.list(); 
     for (int i=0; i<results.size(); i++){ 
      System.out.println("Row "+i+" was:"); 
      A a = (A)results.get(i); 
      System.out.println("Result "+i); 
      System.out.println(a.toString()); 
     } 

     session.getTransaction().commit(); 


    } 
    public void createEntities(Session session){ 
     for (int i=0; i<2; i++){ 
      A a = new A(); 

      B b = new B(); 

      a.setB(b); 

      session.save(a); 

     } 

    } 
    public Session getSession(){ 
     if (sessionFactory == null){ 
      AnnotationConfiguration config = new AnnotationConfiguration(); 
      config.addAnnotatedClass(A.class); 
      config.addAnnotatedClass(B.class); 
      config.configure(); 
      new SchemaExport(config).create(true,true); 

      sessionFactory = config.buildSessionFactory(); 
     } 
     Session session = sessionFactory.getCurrentSession(); 

     return session; 
    } 

} 

最後的日誌輸出,顯示額外的選擇取回相關類

2 [main] INFO org.hibernate.cfg.annotations.Version - Hibernate Annotations 3.5.1-Final 
23 [main] INFO org.hibernate.cfg.Environment - Hibernate 3.5.1-Final 
28 [main] INFO org.hibernate.cfg.Environment - hibernate.properties not found 
32 [main] INFO org.hibernate.cfg.Environment - Bytecode provider name : javassist 
37 [main] INFO org.hibernate.cfg.Environment - using JDK 1.4 java.sql.Timestamp handling 
160 [main] INFO org.hibernate.annotations.common.Version - Hibernate Commons Annotations 3.2.0.Final 
176 [main] INFO org.hibernate.cfg.Configuration - configuring from resource: /hibernate.cfg.xml 
176 [main] INFO org.hibernate.cfg.Configuration - Configuration resource: /hibernate.cfg.xml 
313 [main] INFO org.hibernate.cfg.Configuration - Configured SessionFactory: null 
338 [main] INFO org.hibernate.dialect.Dialect - Using dialect: org.hibernate.dialect.MySQLDialect 
462 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: com.play.hibernate2.Test2 
545 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity com.play.hibernate2.Test2 on table Test2 
649 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: com.play.hibernate2.Test3 
650 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity com.play.hibernate2.Test3 on table Test3 
651 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: com.play.hibernate2.A 
651 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity com.play.hibernate2.A on table A 
653 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: com.play.hibernate2.B 
653 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity com.play.hibernate2.B on table B 
678 [main] INFO org.hibernate.cfg.AnnotationConfiguration - Hibernate Validator not found: ignoring 
687 [main] INFO org.hibernate.tool.hbm2ddl.SchemaExport - Running hbm2ddl schema export 
688 [main] INFO org.hibernate.tool.hbm2ddl.SchemaExport - exporting generated schema to database 
691 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - Using Hibernate built-in connection pool (not for production use!) 
691 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - Hibernate connection pool size: 1 
698 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - autocommit mode: false 
711 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - using driver: com.mysql.jdbc.Driver at URL: jdbc:mysql://localhost:3306/play 
711 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - connection properties: {user=play, password=****} 

    alter table A 
     drop 
     foreign key FK412E010759 

    alter table Test2 
     drop 
     foreign key FK4CF5DC04B7E1B79 

    drop table if exists A 

    drop table if exists B 

    drop table if exists Test2 

    drop table if exists Test3 

    create table A (
     id integer not null auto_increment, 
     b_id integer, 
     primary key (id) 
    ) 

    create table B (
     id integer not null auto_increment, 
     primary key (id) 
    ) 

    create table Test2 (
     id integer not null auto_increment, 
     name varchar(255), 
     value integer not null, 
     test3_id integer, 
     primary key (id) 
    ) 

    create table Test3 (
     id integer not null auto_increment, 
     name varchar(255), 
     value integer not null, 
     primary key (id) 
    ) 

    alter table A 
     add index FK412E010759 (b_id), 
     add constraint FK412E010759 
     foreign key (b_id) 
     references B (id) 

    alter table Test2 
     add index FK4CF5DC04B7E1B79 (test3_id), 
     add constraint FK4CF5DC04B7E1B79 
     foreign key (test3_id) 
     references Test3 (id) 
2562 [main] INFO org.hibernate.tool.hbm2ddl.SchemaExport - schema export complete 
2564 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - cleaning up connection pool: jdbc:mysql://localhost:3306/play 
2571 [main] INFO org.hibernate.cfg.search.HibernateSearchEventListenerRegister - Unable to find org.hibernate.search.event.FullTextIndexEventListener on the classpath. Hibernate Search is not enabled. 
2575 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - Using Hibernate built-in connection pool (not for production use!) 
2575 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - Hibernate connection pool size: 1 
2575 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - autocommit mode: false 
2575 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - using driver: com.mysql.jdbc.Driver at URL: jdbc:mysql://localhost:3306/play 
2575 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - connection properties: {user=play, password=****} 
2622 [main] INFO org.hibernate.cfg.SettingsFactory - RDBMS: MySQL, version: 5.1.30 
2622 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC driver: MySQL-AB JDBC Driver, version: mysql-connector-java-5.1.9 (Revision: ${svn.Revision}) 
2633 [main] INFO org.hibernate.dialect.Dialect - Using dialect: org.hibernate.dialect.MySQLDialect 
2635 [main] INFO org.hibernate.engine.jdbc.JdbcSupportLoader - Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4 
2636 [main] INFO org.hibernate.transaction.TransactionFactoryFactory - Using default transaction strategy (direct JDBC transactions) 
2638 [main] INFO org.hibernate.transaction.TransactionManagerLookupFactory - No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended) 
2638 [main] INFO org.hibernate.cfg.SettingsFactory - Automatic flush during beforeCompletion(): disabled 
2638 [main] INFO org.hibernate.cfg.SettingsFactory - Automatic session close at end of transaction: disabled 
2638 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC batch size: 15 
2638 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC batch updates for versioned data: disabled 
2638 [main] INFO org.hibernate.cfg.SettingsFactory - Scrollable result sets: enabled 
2638 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC3 getGeneratedKeys(): enabled 
2638 [main] INFO org.hibernate.cfg.SettingsFactory - Connection release mode: auto 
2639 [main] INFO org.hibernate.cfg.SettingsFactory - Maximum outer join fetch depth: 2 
2639 [main] INFO org.hibernate.cfg.SettingsFactory - Default batch fetch size: 1 
2639 [main] INFO org.hibernate.cfg.SettingsFactory - Generate SQL with comments: enabled 
2639 [main] INFO org.hibernate.cfg.SettingsFactory - Order SQL updates by primary key: disabled 
2639 [main] INFO org.hibernate.cfg.SettingsFactory - Order SQL inserts for batching: disabled 
2639 [main] INFO org.hibernate.cfg.SettingsFactory - Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory 
2641 [main] INFO org.hibernate.hql.ast.ASTQueryTranslatorFactory - Using ASTQueryTranslatorFactory 
2641 [main] INFO org.hibernate.cfg.SettingsFactory - Query language substitutions: {} 
2641 [main] INFO org.hibernate.cfg.SettingsFactory - JPA-QL strict compliance: disabled 
2641 [main] INFO org.hibernate.cfg.SettingsFactory - Second-level cache: enabled 
2641 [main] INFO org.hibernate.cfg.SettingsFactory - Query cache: disabled 
2644 [main] INFO org.hibernate.cfg.SettingsFactory - Cache region factory : org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge 
2644 [main] INFO org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge - Cache provider: org.hibernate.cache.NoCacheProvider 
2644 [main] INFO org.hibernate.cfg.SettingsFactory - Optimize cache for minimal puts: disabled 
2644 [main] INFO org.hibernate.cfg.SettingsFactory - Structured second-level cache entries: disabled 
2648 [main] INFO org.hibernate.cfg.SettingsFactory - Echoing all SQL to stdout 
2648 [main] INFO org.hibernate.cfg.SettingsFactory - Statistics: enabled 
2649 [main] INFO org.hibernate.cfg.SettingsFactory - Deleted entity synthetic identifier rollback: disabled 
2649 [main] INFO org.hibernate.cfg.SettingsFactory - Default entity-mode: pojo 
2649 [main] INFO org.hibernate.cfg.SettingsFactory - Named query checking : enabled 
2649 [main] INFO org.hibernate.cfg.SettingsFactory - Check Nullability in Core (should be disabled when Bean Validation is on): enabled 
2697 [main] INFO org.hibernate.impl.SessionFactoryImpl - building session factory 
2796 [Finalizer] INFO org.hibernate.connection.DriverManagerConnectionProvider - cleaning up connection pool: jdbc:mysql://localhost:3306/play 
2929 [main] INFO org.hibernate.impl.SessionFactoryObjectFactory - Not binding factory to JNDI, no JNDI name configured 
Hibernate: 
    /* insert com.play.hibernate2.B 
     */ insert 
     into 
      B 

     values 
      () 
Hibernate: 
    /* insert com.play.hibernate2.A 
     */ insert 
     into 
      A 
      (b_id) 
     values 
      (?) 
Hibernate: 
    /* insert com.play.hibernate2.B 
     */ insert 
     into 
      B 

     values 
      () 
Hibernate: 
    /* insert com.play.hibernate2.A 
     */ insert 
     into 
      A 
      (b_id) 
     values 
      (?) 
NOW WITH A NEW TRANSACTION 
Hibernate: 
    /* 
from 
    A */ select 
     a0_.id as id2_, 
     a0_.b_id as b2_2_ 
    from 
     A a0_ 
Hibernate: 
    /* load com.play.hibernate2.B */ select 
     b0_.id as id3_0_ 
    from 
     B b0_ 
    where 
     b0_.id=? 
Hibernate: 
    /* load com.play.hibernate2.B */ select 
     b0_.id as id3_0_ 
    from 
     B b0_ 
    where 
     b0_.id=? 
Row 0 was: 
Result 0 
[email protected] 
Row 1 was: 
Result 1 
[email protected] 

編輯號碼3:

如果我做的事情羅斯的方式,與負載,一個左外連接被創建。如果我用一個列表來做,就會發出單獨的選擇。這是相關的代碼。只有改變這種行爲才能重現差異:

/* generates the left outer join 
    A a = (A)session.load(A.class,1); 
    System.out.println(a.getId()+" = "+a.getB().getName()); 
    */ 

    // Creates separate selects for each object b associated with each a 
    Query query = session.createQuery("from A"); 
    List results = query.list(); 
    A a = (A)results.get(0); 
    System.out.println(a.getId()+" = "+a.getB().getName()); 

我想它可能被稱爲'錯誤'。正如我前面提到的,在文檔中,他們說在HQL中而不是在映射中指定獲取模式是'平常的',我認爲這可能意味着HQL方式已經有更多的人流量來處理它。 。?

(順便說一下我增加了一個額外的「名稱」字段A和B,否則冬眠優化了檢索,因爲它可以只是從一個外鍵讓所有B的)

+0

只是一個想法:我看到你的註釋在getter上 - 對Test2的所有其他成員來說,這是一樣的嗎?如果沒有,修復它可能會解決您的問題。 – 2010-05-28 19:55:14

+0

謝謝彼得。是的,他們都在吸氣(但我過去犯了這個錯誤,它確實打破了事情..) – Jeremy 2010-05-28 20:03:13

+0

可悲的是迭代不起作用 - 事實上它更糟!現在它執行初始選擇,它爲對象id提供對象,然後爲每個關聯對象進行選擇,但是通過關聯器表執行左外連接,而不是直接轉到相關對象 - 一個更復雜的單獨選擇! (請參閱下面我對你的回覆的評論)哦,好吧。我認爲這將是HQL的安全,這可能是更好的,因爲它更明確.. – Jeremy 2010-05-28 23:33:29

回答

4

當我從數據庫中選擇的Test2,我可以看到一個單獨的選擇正在取得了解詳細內容相關的test3類。

我對對方的回答的代碼很感興趣,因爲這是我所看到過的測試代碼時,你正在展示,它生成兩個選擇了from Test2

我用下面的依賴關係:

  • org.hibernate作爲:休眠-的EntityManager:罐子:3.4.0.GA:編譯
  • org.hibernate作爲:EJB3持久性:罐子:1.0。 2.GA:compile
  • org.hibernate作爲:休眠公地的註解:罐子:3.1.0.GA:編譯
  • org.hibernate作爲:冬眠的註解:罐子:3.4.0.GA:編譯
  • org.hibernate:hibernate-core:jar:3.3.0.SP1:compile

我將FetchType設置爲EAGER超出了絕望,即使它對OneToOne映射默認爲EAGER,但它沒有區別。

如果您使用Hibernate註釋,因爲Hibernate註釋會覆蓋EJB3抓取選項,所以這沒有影響。請參閱2.4.5.1. Lazy options and fetching modes

+0

感謝您抽出寶貴時間,Pascal :-)這很好,可以得到一些複製。我簡化了上面的測試用例。我猜想在我的設置中,有人會發現有一個錯誤,或者在這種情況下在冬眠中有一些有趣的東西,儘管沒有羅斯提出的那個。 – Jeremy 2010-05-28 22:56:24

+0

我接受你的答案是正確的,部分是爲了測試這個問題(如果可以的話,Ross也會這麼做,我也會正確地標記他的答案),但是也可以通過複製它來防止我發瘋.-) – Jeremy 2010-05-28 23:48:51

2

我創建了一個非常簡單的應用測試你得到的場景和你的代碼應該工作(它對我有用)。我試過的唯一的事情會給我多個select語句,將max_fetch_depth設置爲0.如果設置爲2(或未配置),我在我的查詢中獲得左外連接。你使用的是什麼版本的hibernate?我正在使用3.4.0.GA.

編輯: 下面是簡單的應用程序我用(與帕斯卡提到的相同版本):

CFG:

<hibernate-configuration> 
    <session-factory> 
     <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property> 
     <property name="hibernate.connection.url">jdbc:hsqldb:hibscribs</property> 
     <property name="hibernate.connection.username">sa</property> 
     <property name="hibernate.connection.password"></property> 
     <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property> 
     <property name="show_sql">true</property> 
     <property name="format_sql">true</property> 
     <property name="hbm2ddl.auto">create-drop</property> 
     <property name="current_session_context_class">thread</property> 
     <!-- property name="max_fetch_depth">0</property--><!-- uncomment to see where 2 selects are used instead of join --> 

     <mapping class="com.mydomain.bo.Person" /> 
     <mapping class="com.mydomain.bo.Phone" /> 

    </session-factory> 
</hibernate-configuration> 

Person實體 - 保持它的簡單隻有@OneToOne,加JoinColumn等沒有任何區別。

@Entity 
@Table(name="person") 
public class Person { 
    private Long id; 
    private String name; 
    private Phone phone; 

    @Id 
    public Long getId() { 
     return id; 
    } 
    public void setId(Long id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 

    @OneToOne(cascade=CascadeType.ALL) 
    public Phone getPhone() { 
     return phone; 
    } 

    public void setPhone(Phone phone) { 
     this.phone = phone; 
    } 
} 

@Entity 
@Table(name="phone") 
public class Phone { 
    private Long id; 
    private String number; 

    @Id 
    public Long getId() { 
     return id; 
    } 
    public void setId(Long id) { 
     this.id = id; 
    } 

    public String getNumber() { 
     return number; 
    } 
    public void setNumber(String number) { 
     this.number = number; 
    } 
} 

簡單的測試:

SessionFactory session = HibernateUtil.getSessionFactory(); 
Session sess = session.getCurrentSession(); 
Transaction tx = sess.beginTransaction(); 

Phone phone = new Phone(); 
phone.setId(1L); 
phone.setNumber("1234567"); 

Person person = new Person(); 
person.setId(1L); 
person.setName("Bob"); 
person.setPhone(phone); 

sess.save(person); 

tx.commit(); 

sess = session.openSession(); 

//Person p1 = (Person)sess.load(Person.class,1L); 
//System.out.println(p1.getPhone().getNumber()); 

// changed the above code to use the Criteria interface below: 
Criteria criteria = sess.createCriteria(Person.class); 
List<Person> results = criteria.list(); 
for (int i=0; i<results.size(); i++){ 
    Person p = (Person)results.get(i); 
    System.out.println(p.getPhone().getNumber()); 
} 

輸出:

Hibernate: 
    select 
     phone_.id, 
     phone_.number as number1_ 
    from 
     phone phone_ 
    where 
     phone_.id=? 
Hibernate: 
    insert 
    into 
     phone 
     (number, id) 
    values 
     (?, ?) 
Hibernate: 
    insert 
    into 
     person 
     (name, phone_id, id) 
    values 
     (?, ?, ?) 
Hibernate: 
    select 
     person0_.id as id0_1_, 
     person0_.name as name0_1_, 
     person0_.phone_id as phone3_0_1_, 
     phone1_.id as id1_0_, 
     phone1_.number as number1_0_ 
    from 
     person person0_ 
    left outer join 
     phone phone1_ 
      on person0_.phone_id=phone1_.id 
    where 
     person0_.id=? 
1234567 
+0

感謝您花時間測試這一點,羅斯。我真的很感激它..我粘貼了一個較小測試的完整代碼。如果在您的設置中可以正常工作,我會非常感興趣。它在我的工作不起作用,即使在3.5以下。1-Final,但它可能是我的代碼中的東西,所以我已經粘貼了所有它。謝謝:-) – Jeremy 2010-05-28 22:54:23

+0

好的 - 我們正在追蹤這個。如果我執行加載操作,則會發生左外連接行爲。但是,如果我執行list(),然後獲取列表中的第一個對象,它會執行兩個選擇 - 在最初的問題 – Jeremy 2010-05-28 23:08:29

+0

中查看我的編輯編號3是的,我得到的結果與您相同。而不是使用列表嘗試使用迭代 - 我給了一個嘗試,似乎工作 – Ross 2010-05-28 23:18:12

17

作爲蒸餾:如果您使用的查詢界面(例如:session.createQuery())

@Fetch(JOIN)將被忽略,但它如果使用標準接口可以正常使用。

這實際上是Hibernate中一個從未解決的錯誤。這很不幸,因爲很多應用程序都使用Query接口,並且無法輕鬆遷移到Criteria接口。

如果使用Query接口,則必須手動將JOIN FETCH語句添加到HQL中。

+0

我很想知道爲什麼發生這種情況,並沒有提到任何地方。 謝謝先生。我的公司和我自己欠你一筆大交易。 – 2013-07-01 08:59:49

+2

@EyadEbrahim實際上文檔很清楚:*「表示關聯獲取策略,它與Criteria API一起用於指定運行時獲取策略。對於HQL查詢,請使用FETCH關鍵字。」* http:// docs。 jboss.org/hibernate/core/3.3/api/org/hibernate/FetchMode.html – JCasso 2013-11-08 07:10:28

+0

另一個提醒我應該在我說之前閱讀。 – 2013-11-08 13:28:37