(Spring / Hibernate)初始化子对象策略

时间:2013-09-17 10:38:27

标签: java spring hibernate spring-webflow

我有一个应该绑定到包含很多子节点的复杂对象的表单,每次在加载此表单之前,我必须在只有很多new语句的方法中初始化所有子对象并调用setter方法,我必须为许多表单和其他复杂对象重复此方案

是否有比initializeEmployee方法更好的策略?

例如:

@Entity
public class Employee {
    Integer Id;
    Contract contract;
    Name name;
    List<Certificate> list;
    // getter and setters
}

@Entity
public class Contract {
    String telephoneNum;
    String email;
    Address address;
    // getter and setters
}

@Entity
public class Address {
    String streetName;
    String streetNum;
    String city;
}

public class Name {
    String fName;
    String mName;
    String lName;
    // getter and setters
}

// And another class for certificates

public initializeEmployee() {
    Employee emplyee = new Employee();

    Name name = new Name();
    employee.setName(name);

    Contract contract = new Contract();
    Address  address = new Address();
    contract.setAddress(address);
    employee.setContract(contract);

    // set all other employee inner objects, 
}

修改 根据以下答案,似乎没有最佳答案。但是,我可以使用实体constructorFactory设计模式。

但是在使用Required和Optional字段初始化所有字段策略时,这两个解决方案都无法解决我的其他问题。

例如: 如果我根据需要Name(即如果Name对象属性为空,则Employee实体不会持久化,另一方面Contract实体是可选的。我不能保持空{{1}对象到数据库,所以我必须在持久化之前先使它Contract,然后在持久性之后重新初始化它,如下所示

null

4 个答案:

答案 0 :(得分:7)

你可以向你的实体添加构造函数(毕竟它们是它们的角色),如果空值对你的情况没有意义,就可以实例化这些字段。

另一种方式,如果你不喜欢添加构造函数,就是添加一个静态工厂方法来实现你的bean,它看起来像initializeEmployee()但是带有潜在的参数并返回一个Employee对象。 http://en.wikipedia.org/wiki/Factory_method_pattern

同样,您也可以实例化您的集合,因为空集合可能没有任何意义(但是有一个空集合)。

您可以向实体添加行为,不要被锁定在Anemic Domain Model中,这被Martin Fowler视为反模式http://www.martinfowler.com/bliki/AnemicDomainModel.html

修改

我看到你正在使用dao.persist(实体):你可能正在使用JPA。如果是这样,也许最好不要修改你的对象图(在正面)并为Employee添加一个EntityListener(在持久层中):这里是Hibernate EntityListener的链接(它是一个JPA特性,所以如果你是使用另一个框架不要担心)http://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/listeners.html

使用EntityListener,您可以在持久性和之后添加小的“aop like”操作。这将允许您不处理域和前层上的空值,并确保每个实体都适合任何情况(更好的验证)。

在PrePersist中:你们添加你的代码来检查空值(可能在域类上使用自定义方法“isEmpty()”)并在需要时使字段无效。在PostPersist中添加新对象。

答案 1 :(得分:4)

我无法得到你真正需要的东西,但我想你可以这样试试:

@Entity
public class Employee {
    Integer Id;
    Contract contract = new Contract();
    Name name = new Name();
    List<Certificate> list;
    // getter and setters
}

@Entity
public class Contract {
    String telephoneNum;
    String email;
    Address address = new Address();
    // getter and setters
}

答案 2 :(得分:2)

我不确定它是否会降低详细程度,但由于这是一个UI问题,您可以初始化flow.xml中的可编辑对象,然后在保存到数据库之前将它们全部放在Employee实例中。

<on-start>
    <evaluate expression="new foo.bar.Name()" result="flowScope.employeeName" />
    <evaluate expression="new foo.bar.Contract()" result="flowScope.contract" />
    <evaluate expression="new foo.bar.Address()" result="flowScope.address" />
</on-start>

答案 3 :(得分:1)

实际上我建议不要直接在GUI中使用Hibernate Entities。在许多情况下(我也假设你的,但我遗漏了一些关于你的用例的细节),使用数据传输对象模式是很有用的。您可以创建特定于GUI的DTO,只包含您需要的那些字段,并且结构只需要复杂。

在特定用户操作(例如保存)之后,使用这些DTO(在事件处理上)来创建将被保留的实体。

除非你的情况只是进入GUI屏幕导致实体创建,否则我会推荐工厂模式。

另请注意,在许多情况下,构成主对象(在您的示例中为Employee)的组件对象的初始化最好在主对象的构造函数中初始化,例如。如果您希望Contract不能为null - 在构造函数中初始化它。证书和其他人的名单也是如此。