Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(Spring / Hibernate) Initialize children objects strategy

I have a form that should be bind to a complex object that wrap a lot of children, every time before loading this form I have to initialize all children object in a method that only have a lot of new statements and calling a setter method, I have to repeat this scenario for a lot of forms and other complex objects

Is there a better strategy than the initializeEmployee method?

For example:

@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, 
}

EDIT: According to below answers, it seems that there is no optimal answer. However, I could use the Entity constructor or a Factory Design Pattern.

But both solutions don't solve my other problem in initializing all fields strategy with Required and Optional fields.

For example: If I have Name as required (i.e. the Employee entity will not persisted if Name object attributes are empty, on the other side the Contract entity is an optional. and I cannot persist an empty Contract object to the database, so I have to make it null first before persistence, then reinitialize it after persistence like the following

// Set Contract to null if its attributes are empty
Contract contract = employee.getContract()
if(contract.getTelephoneNum().isEmpty && contract.getEmail().isEmpty() && contract.getAddress().isEmpty()){
    empolyee.setContract(null);
}

employeeDAO.persist(employee);
// reinitialize the object so it could binded if the the user edit the fields.
employee.setContract(new Contract());
like image 516
fujy Avatar asked Sep 17 '13 10:09

fujy


2 Answers

You can add constructors (it is their role after all) to your entities to instanciate these fields if having a null value has no meaning for your case.

Another way, if you don't like adding contructors, is to add a static factory method to instanciate your bean which will look like initializeEmployee() but with potential parameters and returning an Employee object. http://en.wikipedia.org/wiki/Factory_method_pattern

Similarly, you can instanciate your collections too, as there is probably no meaning for a null collection (but there is one for an empty collection).

You can add behaviour to your entities, don't be locked in Anemic Domain Model which is considered an anti-pattern by Martin Fowler http://www.martinfowler.com/bliki/AnemicDomainModel.html

EDIT

I see you are using dao.persist(entity): you are probably using JPA. If so, maybe it is best to not modify your object graph (on the front side) and add an EntityListener (in the persistence layer) for Employee: here is a link for Hibernate EntityListener (it is a JPA feature, so if you are using another framework don't worry) http://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/listeners.html

With an EntityListener, you can add small "aop like" actions before persistence and after. This will allow you to not deal with null values on the domain and front layers and will ensure that every entity fits in any case (better validation).

In PrePersist: you'all add your code to check null values (possibly with custom methods "isEmpty()" on the domain classes) and nullify fields if needed. In PostPersist you add your new object.

like image 195
zenbeni Avatar answered Sep 23 '22 01:09

zenbeni


I couldn't get what you really need, but I think you could try this way:

@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
}
like image 37
Timofey Gorshkov Avatar answered Sep 22 '22 01:09

Timofey Gorshkov