我正在尝试构建一个测试网站,该网站使用JSF 2.0,EJB 3.1和JPA 2.0显示有关学生的各种信息。
学生登录后,学生可以浏览不同的页面以显示不同类型的信息,这是通常的注册管理系统所做的事情。假设根据一个页面中的登记信息显示时间表,并在另一个页面中显示分配。将显示的信息包括学生的属性,映射的实体,如注册课程,提交的作业等。
首先,我尝试创建一个无状态bean并获取每个页面所需的信息,并更改学生的一些属性
@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);
}
}
assignment.xhtml:
<h:datatable value="#{assignmentBean.assignments}"></h:datatable>
然后,我发现将学生从托管bean传递给无状态ejb,一次又一次地检索学生,然后只将一部分信息返回给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);
}
}
assignment.xhtml:
<h:datatable value="#{loginSession.studentDao.currentStudent.submittedAssignments}"></h:datatable>
由于currentStudent
与扩展持久化上下文一起存在,我可以直接检索信息。并且我不必为每个操作一次又一次地将SID传递给EJB,也适用于一次又一次地找到该学生,因为它已经在那里管理。
我不确定是否滥用@Stateful
bean,因为网页是一大堆对话,不像普通的购物车&#34;例如,用户可以选择大量订单,进行付款,然后在验证和用户确认后提交所有数据库更改。
请评论上述SFSB用法是否滥用SFSB以及为什么如果是滥用,或者上述两种设计中的哪一种更好(或者如果两者都不好则建议另一种,因为我是第一次写作一个Web应用程序,从废料开始,但是来自Apress的一些书籍,那些以Pro,EJB3,JPA,JSF,带有glassfish等的Java EE 6开头的那些书。)
谢谢。
答案 0 :(得分:1)
如果您使用有状态会话bean,EJB容器代表您的客户端管理状态,因此不需要传递ID:它更舒服。
在你的情况下,没关系。
一般来说,请考虑以下事项:
@Remote
:如果客户端和服务器不在同一个JVM上,则每个方法调用都需要编组,然后通过网络。List
,其数量和内容很可能随着时间的推移而增长。使用无状态设置,您可以设计一个仅在浏览器中管理状态的应用程序,例如。由于这些原因,我总是更喜欢使用数据传输对象的无状态设置。但同样,在你的情况下,没关系。