我正在学习春天的冬眠。实现时,我正在创建实体类,如下所示
@Entity
@Table(name = "USER_DETAILS", uniqueConstraints = @UniqueConstraint(columnNames = "USER_ID"))
public class UserInfo implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "USER_KEY", unique = true, nullable = false)
private Long userKey;
@Column(name = "USER_ID", unique = true, nullable = false)
private String userId;
//getters and setters
}
我正在设计一个html页面以获得用户的上述输入。根据教程,他们创建了一个DTO类,它具有相同的变量,这些变量位于DAO实体类中,并在将DTO附加到下面的表单后实现JSR303验证。
<sf:form action="/addUser" commandName="userDTO"
method="post">
//input text boxes
</sf:form>
很难理解为什么我们需要在没有hibernate注释和DTO名称中的相同变量的情况下再次创建相同的DAO实体类。请分享一些指导方针。
这是一种最佳做法,还是我们需要为html表单创建DTO类的任何性能/结构原因。
如果我们直接将DAO实体类与表单相关联,会发生什么。
请提供一些想法/指导。
答案 0 :(得分:1)
对于像宠物应用程序这样的简单应用程序,您可以使用实体进行Web层。 当您在实体模型中添加N对多关系时,会出现第一个问题。
Hibernate使用接口列表Set,但是它有自己的实现,比如PersistentSet,它保存了关于hibernate会话的信息,你的web部分/ level也应该有hibernate jar来处理set的这个实现:)
延迟加载。如果你关闭hibenate会话你会得到LazyInitializationException,你要避免这种情况,你应该保持你的hib会话打开,直到你没有完成与web级别的实体一起工作
答案 1 :(得分:1)
这个问题的简单答案:
考虑一个例子:
要获得客户订单的摘要,那将从客户,地址,产品,订单等实体中获取每一行。在这种情况下,将所有实体加载到内存以呈现它们是浪费且缓慢的在平面搜索结果屏幕中。
现在,只要视图发生更改,就无法更改实体(这将非常耗时),但DTO可以轻松更新或删除,因为它们仅用于获取数据并进行渲染。 / p>
强烈建议将尽可能多的业务逻辑放入实体中,并尝试使用所有创建和连接实体的代码默认/包保护并尽可能隐藏。当你这样做时,你会得到更好的OO设计。一个例子是Order实体有一个方法getOrderItems列出OrderItem实体但是一个受保护的setOrderItems方法。客户端将在Order上调用一个名为addItem的公共方法,该方法使用受保护的构造函数在内部构建OrderItem条目所需的所有字段,并将其添加到其订单项列表中。订单成为&#34;根/聚合实体&#34;它管理下属实体的关系和业务逻辑。这是一种更自然的OO设计,而不是“无行为”的设计。 DTO的业务逻辑完全在服务类中;或更糟糕的是在UI代码中传播。查询和加载根实体的服务类然后在包含业务逻辑的根实体上调用方法。这样,使用相同根实体的不同服务类方法不会复制逻辑,因为逻辑将在共享的实体内。
简单来说:如果您的实体愚蠢而没有逻辑,那么它们只是DTO。
答案 2 :(得分:0)
在我看来,我们将dao实体类与mvc形式联系起来很糟糕。
将应用程序隔离到某些层是一个更好的主意。最常用的方法是有3层:持久性,服务和表示层。
通常,每个图层都使用自己的对象:
我们需要这个,因为我们希望每个图层与其他图层分开。如果要在控制器中使用实体,则演示文稿将取决于数据的存储方式。这真的很糟糕。它甚至不应该知道数据的存储或存储方式。