我有一个关于访问模型对象的成员变量的简单问题。
我有以下模型对象:
@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
都可以有一个account
。从zentask示例复制Account
对象。身份验证后,我重定向到索引页面,该页面显示Person.name
成员变量中所述的用户realname。 Account
对象插入到页面中,就像zentasks示例一样:
Account.find.byId(Controller.request().username());
现在模板中发生以下奇怪的事情,我不明白:
@account.person.name
会在调用时在模板中插入Null
值:
@account.person.getName() or @account.person.getName
按预期结果,从person对象插入正确的名称。
@account.person
显示person对象的.toString()
,也正确显示名称。
总结一下:上面的代码出了什么问题?为什么我可以毫无问题地调用account.person值,但是当我调用account.person.name时这不再起作用
提前谢谢!
理查德
答案 0 :(得分:3)
这是因为JPA使用Aspects来拦截getter使用并从延迟加载的对象中填充缺少的数据。我不知道传统思维是什么,但由于这个原因我不会使用JPA的公共成员,它会一直打破框架。
如果你真的想使用公共成员,你必须将关系标记为渴望获取:
@OneToMany(fetch=FetchType.EAGER)
或显式获取模板中所需的所有对象树(呃)。
在你的情况下,关系,OneToOne是在关系的另一端定义的,如果你在Account端定义它,它应该默认获取eager。我忘记了你是否可以在两个实体上定义OneToOne,我认为你可以,但你可能需要稍微调整一下。
总的来说,不要将公共成员与JPA一起使用,它会破坏。更好的是,抛弃JPA并使用Anorm,它比JPA更成功地映射到问题域。像这样的问题一直导致JPA实现占用的实现时间是任何人似乎能够预测的两倍。
答案 1 :(得分:1)
我偶然发现了Guillaume Bort发布的答案,该答案解释了事情。 在这里阅读:
https://groups.google.com/d/topic/play-framework/CNjH3w_yF6E/discussion
希望这有帮助!
答案 2 :(得分:0)
由于延迟加载,字段中的值只有在从类本身访问时才会被加载。(在正常情况下会使用setter / getter
为了加载你以太必须写入getter和setter的值。 或者您可以创建一个检查每个值的方法。
您可以将以下方法添加到您的帐户实体:
public void checker(){
if(email==null){}
if(password==null){}
if(person==null){}
}
这将加载每个值,但不会降低性能