2012-11-01 46 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