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

时间:2008-12-18 14:50:04

标签: java spring spring-mvc

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

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

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

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显式填充所有内容,即使从数据库中没有检索到任何内容。或者给工厂一个方法来浏览对象并“填写”任何遗漏的东西。

建议?

4 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分:3)

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

在你给出的情况下,我可能会把初始化放在getter中,所以只有在实际使用时才会实例化子对象,即:当调用getter时,只有当它为null时才会实现。

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

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

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

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:1)

我已经使用了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。

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