我正在尝试构建一个测试网站,显示有关具有 JSF 2.0、EJB 3.1 和 JPA 2.0 的学生的各种信息。
学生登录后,可以浏览不同的页面,显示不同的信息,这就是通常的注册管理系统所做的。比如说在一个页面中根据注册信息显示时间表,在另一页面中显示作业。将显示的信息包括学生的属性、映射的实体(如注册课程、提交的作业等)。
起初,我尝试创建一个无状态bean并获取每个页面所需的信息,并更改student的一些属性
@Entity
public class Student{
@Id
private String sid;
private String address;
@ManyToMany
private List<Assignment> submittedAssignments;
@ManyToMany
private List<Course> courses;
}
@Stateless
@LocalBean
public class studentDao {
@PersistenceContext(unitName="PU")
private EntityManager em;
public Student getStudent(String sid){
return em.find(Student.class, sid);
}
public List<Course> getCoursesByStudent(String sid){
return em.find(Student.class, sid).getCourses();
}
public List<Assignment> getAssignmentsByStudent(String sid){
return em.find(Student.class, sid).getSubmittedAssignments();
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void ChangeAddress(String sid, String newAddress){
em.find(Student.class, sid).setAddress(newAddress);
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void SubmitAssignment(String sid, Assignment submittedAssignment){
}
//Some more methods, just list a few for illustration.
}
@ManagedBean
@SessionScoped
public class LoginSession{
private String sid;
//getter
public login(String sid){
//probably will need password validation later, so I have to connect to db and check the password.
this.sid=sid;
}
}
@ManagedBean
@RequestScoped
public class AssignmentBean{
@EJB
private StudentDao studentDao;
@ManagedProperty(value="#{loginSession}")
private LoginSession session;
public List<Assignment> getAssignments(){
return studentDao.getAssignmentsByStudent(session.sid);
}
}
分配.xhtml:
<h:datatable value="#{assignmentBean.assignments}"></h:datatable>
然后,我发现将student从托管bean传递到无状态ejb,一次又一次地检索student,然后只返回一部分信息给ManagedBean进行显示,因此我认为我可以这样做。
@Stateful
@LocalBean
public class studentDao {
@PersistenceContext(unitName="PU", type=PersistenceContextType.EXTENDED)
private EntityManager em;
private Student currentStudent;
public void login(String sid){
//didn't make a password, just type sid and done.
currentStudent = em.find(Student.class, sid);
}
public Boolean getLoggedIn(){
return currentStudent != null;
}
public Student getCurrentStudent(){
return currentStudent;
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void ChangeAddress(String newAddress){
currentStudent.setAddress(newAddress);
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void SubmitAssignment(Assignment submittedAssignment){
}
}
@ManagedBean
@SessionScoped
public class LoginSession{
@EJB
private StudentDao studentDao;
public login(String sid){
studentDao.login(sid);
}
}
分配.xhtml:
<h:datatable value="#{loginSession.studentDao.currentStudent.submittedAssignments}"></h:datatable>
由于currentStudent
具有扩展的持久性上下文,我可以直接检索信息。而且我不必为每个操作一次又一次地将 SID 传递给 EJB,也一次又一次地申请找到那个学生,因为它已经在那里被管理了。
我不确定这是否是对@Stateful
bean 的滥用,因为页面是一大群对话,不像常见的“购物车”示例,用户可以选择很多订单,付款,然后在验证后提交所有数据库更改,用户确认。
请评论上述 SFSB 的使用是否是对 SFSB 的滥用以及为什么是滥用,或者上述两种设计中哪一种更好(或者如果两者都不好,因为我是第一次编写 Web 应用程序,请建议另一种从废品开始,但从 Apress 的几本书开始,那些从 Pro 开始,EJB3、JPA、JSF、Java EE 6 和 glassfish 等)。
谢谢你。