【问题标题】:Scala template accessing model object properties in Play 2.0在 Play 2.0 中访问模型对象属性的 Scala 模板
【发布时间】:2012-03-29 11:36:58
【问题描述】:

我有一个关于访问模型对象的成员变量的简单问题。

我有以下模型对象:

@Entity
public class Person extends Model{
    @Id 
    public Long id;
    public String name;
}

@Entity
public class Account extends Model{
    @Id
    public String email;
    public String password;
    @OneToOne
    public Person person;
}

到目前为止一切顺利,任何给定的person 都可以有一个accountAccount 对象是从 zentask 示例中复制而来的。身份验证后,我重定向到显示用户实名的索引页面,如Person.name 成员变量中所述。 Account 对象被插入到页面中,就像 zentasks 示例一样,如下所示:

Account.find.byId(Controller.request().username());

现在模板中发生了以下奇怪的事情,我不明白:

@account.person.name

调用时会在模板中插入Null 值:

@account.person.getName()  or   @account.person.getName

从 person 对象中插入正确的名称,结果符合预期。

@account.person

显示人员对象的.toString(),同时正确显示名称。

总结一下:上面的代码有什么问题?为什么我可以毫无问题地调用 account.person 值,但是当我调用 account.person.name 时,这不再起作用了

提前谢谢你!

理查德

【问题讨论】:

    标签: templates playframework playframework-2.0


    【解决方案1】:

    这是因为 JPA 使用 Aspects 来拦截 getter 的使用并从延迟加载的对象中填充缺失的数据。我不知道传统的想法是什么,但我永远不会在 JPA 中使用公共成员,因为它会一直破坏框架。

    如果您真的想使用公共成员,则必须将关系标记为渴望获取:

    @OneToMany(fetch=FetchType.EAGER)
    

    或在模板中显式获取您需要的所有对象树(呃)。

    在您的情况下,关系的另一端定义了 OneToOne,如果您在 Account 端定义它,则默认情况下它应该急切地获取。我忘记了你是否可以在两个实体上定义 OneToOne,我想你可以,但你可能不得不稍微摆弄一下。

    总的来说,不要在 JPA 中使用公共成员,它会崩溃。更好的是,抛弃 JPA 并改用 Anorm,它比 JPA 更成功地映射到问题域。此类问题始终导致 JPA 实现占用的实现时间是任何人都可以预测的两倍。

    【讨论】:

    • 嗨,PlexQ!感谢您的回复!这种行为很奇怪,就像 Play!鼓励您在类中使用公共成员的框架。我看到了 JPA(在我的例子中是 Ebean,它在 Play!2.0 中是默认的)如何使用 Aspects 来执行延迟加载。但是人们可能期望这会像上面提到的那样工作。再次感谢!我正在奖励你积分,因为我似乎不会从社区得到关于这个的完整答案。
    • 想到另一个想法:我想知道使用静态编织是否会改善这一点,而不是加载时间编织?我可以发誓我记得可以点切字段访问,只是我使用过的 JPA 实现似乎没有。您使用的是哪个 JPA 提供商?
    • EBean 实现作为默认 ORM 提供者随 Play! 2.0 框架。直到 Play 之前我才听说它!随之而来。
    【解决方案2】:

    我刚刚偶然发现 Guillaume Bort 发布的一个答案,它解释了一些事情。 在这里阅读:

    https://groups.google.com/d/topic/play-framework/CNjH3w_yF6E/discussion

    希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      由于延迟加载字段中的值,只有当您从类本身访问它们时才会加载它们。(在正常情况下会使用 setter/getter

      为了加载值,你必须编写 getter 和 setter。 或者您可以创建一个检查每个值的方法。

      您可以将以下方法添加到您的帐户实体:

      public void checker(){
      
          if(email==null){}
          if(password==null){}
          if(person==null){}
      }
      

      这将加载每个值,但不会降低性能

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-22
        • 2016-06-23
        • 2012-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多