2012-11-01 42 views
3

我正在使用play 2.0.4與Java。我試圖保存並從內存數據庫檢索值提供(Ebean是底層的JPA實現)。 下面是一些示例代碼:Eager fetch似乎並沒有加入

@NoobDisclaimer ("I'm fairly new to Play and JPA") 
@Entity 
public class User extends Model { 

@Id 
public Long id; 

public String name; 

// Does not fetch eagerly. 
@ManyToOne(fetch=FetchType.EAGER) 
private Role role; // Role extends Model { has id and name} 

public static Finder<Long, User> find = new Finder<Long, User>(Long.class, User.class); 

public static List<User> all() { 
    List<User> allUsers = find.all(); 
    for (User u : allUsers) { 
     System.out.println("User:" + u.id + "|" + u.name); // SOP1 
     // System.out.println("Assoc Role:" + u.role.name); //SOP2 
    } 
    return allUsers; 
} 

public static void create(User user) { 
    user.save(); 
} 

}

在index.scala.html, @(用戶:列表[用戶],用戶窗體:表格[用戶])

<h2>@users.size() user(s) found!</h2> 
     <ul> 
      @for(usr <- users) { 
       <li>Name: @usr.name</li> <!-- Displayed --> 
       <li>Role: @usr.role.name</li> <!-- Displays blank value --> 
      } 
     </ul> 

的問題是,當我在控制器中執行User.all()並將其發送到視圖時,user.role未加載,即@ usr.role.name爲空。沒有例外。我已經設置了SQL調試,並且已驗證角色表的外鍵保存在用戶表中。當我在User.all()方法中打印角色名稱(請參閱SOP2)時,會觸發查詢並打印角色名稱。它也顯示在視圖上。

我明白,默認情況下,該角色將被延遲加載,並且PersistenceContext在模板中不可用以加載與用戶關聯的角色。但是,不應該急於獲取所有對象的相關實體嗎?我對 Play和JPA相當陌生,我無法弄清楚如何在加載某些內容時無需通過每個關聯實體就能使其工作。有什麼我失蹤?

在相關說明中,如果必須使用懶惰獲取,我如何確保在獲取用戶時user.role可用於視圖?

+0

我看了[鏈接] http://stackoverflow.com/questions/463349/jpa-eager-fetch-does-not-join但我沒有使用Hibernate(所以@Fetch不可用) 。 – Rajiv

+0

我不明白你爲什麼在這裏使用雙「@」'@@ ManyToOne' –

+0

對不起。這是一個錯字。我糾正了它。 – Rajiv

回答

4

Ebean是底層的JPA實現

Ebean不是一個JPA實現。 Ebean與JPA標準有一點相似之處。它看起來有些相似,因爲它的註釋看起來與JPA的相似。

問題的原因:Ebean不支持@ManyToMany批註上的fetch = ...屬性。

2的解決方案:

  1. 移除註釋取= ...,而是要麼play.db.ebean.Model.Finder<I,T>對象(它實現com.avaje.ebean.Query<T>)或com.avaje.ebean.Ebean對象上使用fetch()方法。

    問題是這裏有兩個單獨的持久庫(play.db.ebean和com.avaje.ebean),它們之間的集成是一個挑戰和問題。
    例如play.db.ebean.Model.Finder.fetch()方法返回com.avaje.ebean.Query<T>,而不是play.db.ebean.Model.Finder - 我發現它無用,因爲它會讓您遠離play API Model helper。在調用fetch()之後,顯然你不能再使用Model.Finder方法 - 在這一點上不是很多「輔助」類。
    說實話,我不認爲抓取功能是Play API中的第一類功能,最好是推遲到Avaje API。

    兩個使用從Avaje API內取()的例子:

    // single SQL query with a fetch join 
    List<Order> l0 = Ebean.find(Order.class) 
    .fetch("customer") 
    .findList(); 
    

    // two separate SQL queries 
    List<Order> l0 = Ebean.find(Order.class) 
    .fetch("customer", new FetchConfig().query()) 
    .findList(); 
    

    注:最後釋放/更新到Ebean(其它的是錯誤修正)爲6 2010年11月 - 整整2年前。 Ebean的攝取率非常低。

  2. 切換到在Play中使用JPA 2.0實現。 JPA的2.0版本確實非常強大,易於使用,並且得到了廣泛的支持。這可能意味着Ebean的死亡。請注意,Play已將以下配置功能添加到2.0中(1.1中不存在) - 這表明Play正朝着來自任何提供商的JPA提供更全面的支持。 http://www.playframework.org/documentation/2.0/JavaJPA

    一旦你這樣做,停止使用play.db類和com.avaje類 - 我建議你使用100%的javax.persistence類。

+0

簡單的解決方案是使用getters/setter,而不是直接訪問字段。我也不得不修改模板以使用訪問者名稱,即'@ usr.role.name'變成了'@ usr.getRole.getName' - 恐怕不是很可讀。 因爲,我不必堅持Ebean,我想我會轉到正確的JPA實現。謝謝Glen! – Rajiv