我想编写一个用于在线学习的Java EE应用程序。我正在考虑这种数据表示:
@Entity
public class Course {
private String name;
private String[] instructors;
private String[] teachingAssistants;
private GradeBook gradeBook;
// plenty of methods
}
@Entity
public class GradeBook {
private GradeBookColumn[];
// some methods
}
@Entity
public abstract class GradeBookColumn {
private String name;
private GradeBookColumnType type;
// more methods
}
我会有更多不仅仅是这个,但你明白了。
现在,在EJB 3.2规范中,实体bean被删除并替换为JPA实体。我的问题是如何应对这一悲惨的损失。序列化JPA实体不适合我的原因有三个:
那么,如何在没有实体bean的情况下设计此系统以满足这些要求?
答案 0 :(得分:1)
我不确定实体bean的损失是否真的很悲惨,但这是一个意见问题:)
您似乎在桌面上有一个连接到远程服务器的富客户端。您有两种选择:
一个。您在客户端和服务器之间交换“detached”对象图。客户端接收一些数据,修改它,然后将其发回。然后服务器“merges”收到它的数据。加载数据时服务器上有一个事务,合并后有一个事务。为确保您没有冲突,您可以对数据进行版本控制。
B中。您使用“extended persistence context”。在这种情况下,客户端会收到仍然“附加”到会话的entites。缓存客户端实体的修改,并在服务器上调用方法时进行同步。
所以,关于你面临的三个设计问题,这是我的看法:
性能。 JPA和其他现代ORM依赖于懒惰以避免不必要的数据传输:数据按需加载。您可以选择热切或懒散地加载图形的哪个部分。使用选项A,您需要确保在将所有必要数据发送到客户端之前加载它们;如果客户端尝试访问未加载的数据,则会收到异常,因为它在事务之外。使用选项B,我猜客户端可以随时延迟加载数据(值得仔细检查)。
安全性。 JPA实体应该是业务对象,而不是数据对象。它们可以封装执行必要检查的业务方法,并保留所需的不变量。换句话说:安全性不是在数据级别处理,而是在业务逻辑级别处理。这适用于选项A和B.
写访问。使用选项A,您需要发回整个图并合并它。使用选项B,框架应该以更优化的方式合并已缓存的更改。
结论:
扩展持久性上下文已经设计用于具有长工作单元的GUI应用程序。他们理论上应该解决你的问题。实际上,扩展持久化上下文虽然具有复杂性(例如需要使用有状态会话bean)。
分离和合并图表的方法更简单,但提出了您在性能方面提到的问题。
第三种选择是回到传统的data transfer object (DTO)来优化性能。在这种情况下,JPA只能在服务器端保留。您只需将真正需要的数据子集转移到DTO中,而不是传输JPA entites。缺点是DTO会激增,您将拥有样板代码来从JPA entites创建DTO,并更新来自DTO的JPA enties。