大家晚上好,这是我在Stack Overflow上的第一篇文章。 我最近已经介绍了Java 6 EE,特别是JPA作为JSF 2.1框架的一部分,现在我正面临一个奇怪的行为,我希望你能帮助我理解。 在我们的项目中(使用NetBeans 7.2开发的),我们有几个一对多的关系,我们希望按照我们导航多对一的方式导航它们。事实上,我们只能在重新启动应用服务器(GlassFish 3.1.2)后才能使其工作,并且此行为仅在下一次部署之前持续;这意味着我们需要在每次应用修改时重新启动Glassfish ... 以下是一些代码摘录,可帮助您了解我们的情况。JPA EAGER fetch只在服务器重启时才起作用
这代表我们的主要实体(人)有,其他人之中,与电子邮件以及与电话,并与ACCOUNTTYPE
@Entity
public class Person implements Serializable {
//
//private non-collection fields including id
//
@OneToMany(mappedBy="person", fetch=FetchType.EAGER)
private Collection<Email> personEmails;
@OneToMany(mappedBy="person")
private Collection<Phone> personPhones;
@ManyToOne
private AccountType accountType;
//
// getter and setter, hashCode, isEqual and toString
//
}
一个多到一的关系的一个一对多的关系而这些电子邮件...
@Entity
public class Email implements Serializable {
//
//private non-collection fields including id
//
private String address;
@ManyToOne
private Person person;
//
// getter and setter, hashCode, isEqual and toString
//
}
... ...电话
@Entity
public class Phone implements Serializable {
//
//private non-collection fields including id
//
private String number;
@ManyToOne
private Person person;
//
// getter and setter, hashCode, isEqual and toString
//
}
...和ACCOUNTTYPE
@Entity
public class AccounType implements Serializable {
//
//private non-collection fields including id
//
private String name;
@OneToMany(mappedBy="accountType")
private Collection<Person> persons;
//
// getter and setter, hashCode, isEqual and toString
//
}
然后,我们设置了一个示例页面来测试Person中的这三个字段是如何被实际获取的。
这代表了XHTML页面...
<h:form id="form">
<h:panelGrid columns="2">
<h:outputLabel value="forename" />
<h:outputLabel value="#{meBean.currentUser.forename}" />
<h:outputLabel value="emails" />
<h:outputLabel value="#{meBean.currentUser.personEmails.size()}" />
<h:outputLabel value="phones" />
<h:outputLabel value="#{meBean.currentUser.personPhones}" />
<h:outputLabel value="accountType" />
<h:outputLabel value="#{meBean.currentUser.accountType.name}" />
</h:panelGrid>
</h:form>
...这控制器
@ManagedBean
@RequestScoped
public class MeBean {
@EJB
private PersonFacade personFacade;
private Person currentUser;
public MeBean() {
init();
}
@PostConstruct
private void init() {
// Hard-coding user details
try {
this.currentUser = this.personFacade.getFromUsername("user1");
this.currentUser.getPersonPhones().isEmpty();
} catch (Exception e) {
}
}
public Person getCurrentUser() {
return currentUser;
}
public void setCurrentUser(Person currentUser) {
this.currentUser = currentUser;
}
}
现在,我们得到的结果是一个我们只希望,如果我们访问网页在重新启动应用程序服务器之后。
forename Alice
emails 2
phones {[sums.groupa.entities.Phone[id=38]]}
accountType Student
如果我们修改任何内容(除了视图)并保存,在不可避免的部署之后,结果会有所不同。
forename Alice
emails 0
phones {[]}
accountType Student
为什么会发生这种情况,我们该如何避免它?
在此先感谢。
AG
一对夫妇贡献者(我要感谢他们的快速回复)要求的PersonFacade实施。
public Person getFromUsername(String username)
{
try
{
Query q = em.createQuery("SELECT p FROM Person p LEFT JOIN FETCH p.personEmails WHERE UPPER(p.username) = :username");
q.setParameter("username", username.toUpperCase());
return (Person) q.getSingleResult();
}
catch (Exception ex)
{
Logger.getLogger(PersonFacade.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
正如你可以看到我试图用fetch连接的建议,但查询走出了太多的结果:它应该只获取一个人物代表Alice和含在personEmails场电子邮件的两个实例,实例,但我怀疑它得到了两个不同的Person实例,每个实例都有一个不同的Email实例。
原始查询如下:再次
SELECT p FROM Person p WHERE UPPER(p.username) = :username
感谢。
AG
什么隐藏在“如果我们修改任何东西”后面?你有什么修改和如何?外观如何得到人并返回? – 2013-03-11 21:38:57
我的意图是“如果我们修改任何东西”,实际上是对托管的bean,会话bean,实体bean或外墙进行的每一项修改。这会导致NetBeans重新部署项目,并由于某些原因“使无效”的渴望获取类型。关于如何实施门面,我将编辑帖子。谢谢 – algu84 2013-03-12 15:06:55