Spring MVC表单支持对象树初始化的最佳实践

如果我有一个具有复杂对象树的表单支持对象 – 比如一个具有Contact Info对象的Person,该对象具有一堆具有一串字符串的Address对象 – 似乎该对象需要完全填充组件我可以绑定它之前的对象。 因此,如果我正在创建一个新的Person,我需要确保它已经从bat中填充了所有组件对象,如果我从数据库中检索Person,我需要确保任何不是的对象从数据库填充后填充空对象。

第一个问题,当然 – 我的上述假设是否正确? 似乎如果我尝试绑定到person.contactInfo.homeAddress.street并且没有ContactInfo,我会得到一个空指针exception。

其次,初始化对象的最佳方法是什么。 我可以想到几种方法。 一种是在声明时初始化所有成员对象:

public class Person { String name; ContactInfo contactInfo = new ContactInfo(); //getters, setters, etc. } public class ContactInfo { String phone; Address homeAddress = new Address(); } 

等等。

另一种方法是让PersonFactory初始化所有东西(或者有一个初始化所有东西的工厂方法Person.getInstance)。

在从数据库中检索Person的情况下,第一种方法将解决问题(即,如果此特定人员在数据库中没有地址,则该对象仍将具有地址),但这将意味着创建每个对象两次。 不知道如何处理这个问题,除非使DAO显式填充所有内容,即使从数据库中没有检索到任何内容。 或者给工厂一个方法来浏览对象并“填写”任何遗漏的东西。

建议?

如果你愿意,可以称它为overkill,但我们最终做的是创建一个通用工厂,它将接受任何对象并使用reflection(递归地)查找所有null属性并实例化一个正确类型的对象。 我使用Apache Commons BeanUtils做到了这一点。

通过这种方式,您可以获取可能来自各种来源的对象(DAO,从XML反序列化,无论如何),将其传递给此工厂,并将其用作表单支持对象,而无需担心绑定所需的内容为空。

不可否认,这意味着实例化我们可能不需要给定表单的属性,但在我们的情况下通常不适用。

我通常会确保对象完全初始化 – 它使得使用更简单的对象,并避免在整个代码中散布空值检查。

在这里给出的情况下,我可能会将初始化放在getter中,这样子对象只有在实际使用时才会被实例化,即:当调用getter时,只有当它为null时才会实例化。

在通过一对一关系从数据库加载方面,我通常会进行连接并加载批次。 性能影响通常很小,但您应该知道可能存在影响。

当涉及到一对多的关系时,我通常会进行延迟加载。 Hibernate将为您提供此function,但如果您自己滚动,那么您只需要一个List的自定义实现,当调用与其内容相关的任何方法时,它会调用相应的DAO。

对于具有一对多关系的此行为的一个例外是,当您获得要迭代的父对象列表以及要对其子项进行迭代的每个父对象时。 显然,性能会很糟糕,因为你实际上可以通过2次调用对数据库进行+ 1次调用。

我想你在谈论像< form:input path="person.contactInfo.homeAddress.street"/> ? 我不清楚,但假设我是对的:):

1)是的,当您编写person.contactInfo.homeAddress.street ,请阅读person.getContactInfo().getHomeAddress().getStreet() 。 如果ContactInfo或HomeAddress或Street对象为null,则调用其中一个方法会引发NullPointException。

2)我通常在声明时初始化成员对象,就像在代码片段中一样。 如果初始化值是无条件的,那么看不到工厂类的好处。 我没有清楚地看到你被迫两次创建一个人的问题……但我可能会感到厌倦;)

我已经使用了Factory方法(不是为它使用单独的类的粉丝,对我来说,在静态方法中使用它更有意义所以它在一个地方)。 我有类似的东西 –

 public static Person getInstanceForContactInfoForm() { ContactInfo contactInfo = ContactInfo.getInstanceForContactInfoForm(); Person person = new Person(contactInfo); // set whatever other properties you need for Person // just enough to 1-render the form and 2-avoid any exceptions return person; } 

如果我从数据库加载Person,我在Person类中有一个名为“initalizeForContactInfoForm”之类的东西。 从数据库加载Person之后,我将在Spring MVC方法调用的方法的Service层中调用此方法,该方法返回Form Backing Object。

我不认为这是一个真正的惯例,它只是我自己制作的一种方法。 我真的没有看到有什么缺点所以如果有人不同意请告诉我…