渴望获取似乎没有加入

时间:2012-11-01 05:31:41

标签: playframework jpa-2.0

我正在使用Java 2.0.4。我正在尝试从播放提供的内存数据库中保存和检索值(Ebean是基础JPA实现)。 这是一些示例代码:

@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中,     @(用户:列出[用户],userForm:表单[用户])

<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调试,并且我已经验证了Role表的外键是保存在User表中的。当我在User.all()方法中打印角色名称时(请参阅SOP2),将触发查询并打印角色名称。它也显示在视图上。

据我所知,默认情况下,角色会被延迟加载,并且模板中的PersistenceContext不可用于加载与用户关联的角色。但是,不应该急切的获取给我一个对象的所有相关的entites?我很新 Play和JPA和我无法弄清楚如何在我加载东西时不经过每个相关实体就能使其工作。有什么我想念的吗?

在相关的说明中,如果我必须使用延迟提取,当获取用户时,如何确保用户可以使用user.role?

1 个答案:

答案 0 :(得分:4)

  

Ebean是基础JPA实现

Ebean不是JPA实施。 Ebean与JPA标准略有不同。它看起来有点类似,因为它的注释看起来与JPA类似。

问题的原因:Ebean不支持@ManyToMany注释的fetch = ...属性。

2个解决方案:

  1. 从注释中删除fetch = ...而是在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 - 我发现它没有用,因为它会让你远离播放API模型助手。在调用fetch()之后,显然你不能再使用Model.Finder方法了 - 在那一点上没有太多的“助手”类。
    说实话,我不认为fetch功能是Play API中的第一类功能 - 最好遵循Avaje API。

    在Avaje API中使用fetch()的两个例子:

    // 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的最后一次发布/更新(其他错误修复)是2010年11月6日 - 整整两年前。 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类。