(Spring / Hibernate) Initialize children objects strategy - java

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());

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.

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
}

I'm not sure it reduces the verbosity at all but since this is a UI issue, you could initialize the editable objects in your flow.xml and then put it all together in an Employee instance prior to saving to the DB.
<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>

Actually I would advise against using Hibernate Entities directly in GUI. In many cases (I assume in yours too, but I'm missing some details on your use-case) it is useful to use a Data Transfer Object pattern instead. You can create such DTO that is GUI specific, has only those fields that you need, and the structure is only as complex as needed.
After specific user action (like save e.g.) use those DTOs (on event handling) to create your Entities that will be persisted.
Unless your case is that just entering the GUI screen causes Entities creation, then I would recommend Factory pattern.
Also note that in many cases initialization of component objects that are making up the main object (Employee in your example) are better to be initialized in constructor of main object, eg. if you expect that Contract cannot be null - initialize it in constructor. The same for the list of Certificates and others.

Related

Apache Ignite : Lazy References

Don't know how to properly formulate the title, but here is the problem.
Let's say I have a class Person and a class Organization and their association type is Many to One. In Java code Person object has a reference to Organization object and Organization has a Collection of Person objects. Both Person and Organization objects are Serializable. In addition to that I have programmed Person in such a way that it is affinity collocated with Organization.
If I put an instance of Person object into the cache (grid node) I would like to serialize only identifier of associated Organization, but not the whole object that is being referenced.
Is there any solution out of the box (some kind of proxy) that will skip serialization of associated object and will lazy load the associated object by identifier on a deserialized instance of Person?
I have already seen a custom solution for Oracle Coherence grid that is based on decorators, but the implementation is extremely complex.
How about storing an ID of an organization instead of the whole Organization object? This is the proper way to collocate people with their organizations.
If you need to store an actual Organization object inside of a Person instance, you may make a transient field and update it lazily, when you access it. Something like this:
class Person {
#AffinityKeyMapped
private int orgId;
private transient Organization org;
// Other fields, constructors, getter, setters.
}
// ...
// Accessor method in DAO logic.
Organization getOrganization(Person person, IgniteCache<Integer, Organization> orgCache) {
Organization org = person.getOrganization();
if (org == null) {
org = orgCache.get(person.getOrganizationId());
person.setOrganization(org);
}
return org;
}
This way org field won't be serialized, when Person is put into Ignite cache. Only orgId will be. And Organization will be requested from cache only once for a Person object. Subsequent calls to getOrganization() will use a saved value.

Is it ok to pass interface of DTO to DAO

It's about passing interface of DTO to DAO.
For example I have following code
public interface User {
String getName();
}
public class SimpleUser implements User {
protected String name;
public SimpleUser(String name) {
this.name = name;
}
#Override
public String getName() {
return name;
}
}
// Mapped by Hibernate
public class PersistentUser extends SimpleUser {
private Long id;
// Constructor
// Getters for id and name
// Setters for id and name
}
I'm using generic DAO. Is it ok if I create DAO with using interface User instead PersistentUser?
User user = new PersistentUser(name);
UserDao.create(user);
I read a lot of topics on stack but not figured out is this approach ok or no. Please help me. Maybe this is stupid and I can achive only problems.
About separating beans.
I did this because some classes I want to share via API module, that can be used outside to create entities and pass them to my application. Because they uses interface I developed so I can pass them to my DAO for persisting.
Generally, I would say it is ok, but there are a few hidden problems. A developer could cast the object down or access some state via a toString method that shouldn't be accessible. If you don't be careful, it could happen that state is serialized as JSON/XML in webservices that shouldn't be serialized. The list goes on.
I created Blaze-Persistence Entity Views for exactly that use case. You essentially define DTOs for JPA entities as interfaces and apply them on a query. It supports mapping nested DTOs, collection etc., essentially everything you'd expect and on top of that, it will improve your query performance as it will generate queries fetching just the data that you actually require for the DTOs.
The entity views for your example could look like this
#EntityView(PersistentUser.class)
interface User {
String getName();
}
Querying could look like this
List<User> dtos = entityViewManager.applySetting(
EntityViewSetting.create(User.class),
criteriaBuilderFactory.create(em, PersistentUser.class)
).getResultList();

how to save values from one class object to another class object

I have two classes(Pojos) name Soldbookdetails.java and Bookdetails.java,
what I want to do is, I have to get data from Bookdetails table(Soldbookdetails.java) and save the same data to my Soldbookdetails table(Soldbookdetails.java).
ActionClass.java
private Double[] id;//With getter and setter
private Double[] quantity; //With getter and setter
Bookdetails book=new Bookdetails();//pojos,//With getter and setter
Soldbookdetails sbook=new Soldbookdetails();//pojos,//With getter and setter
BookdetailsDAO dao=new BookdetailsDAO();
SoldBooksTransactionDAO dao2=new SoldBooksTransactionDAO();
------------
(Note: my both pojo are same only their Class name are different)
My problem: I am unable to save record from Bookdetails.java to Soldbookdetails.java .(See My above ActionClass.java class,inside the execute method , i have mention the ERRROR).
After getting record by Bookid , i am unable to save the record into my Soldbookdetails.java.
Please help me to solve my problem.
Your saveSoldbooks(Soldbookdetails s) method takes an object of Soldbookdetails as argument but you are passing an object of class Bookdetails.
The thing you can do is you can add a method that copies the attributes of an Bookdetails object to an Soldbookdetails object (without the id field). Then you should try to save the object of Soldbookdetails using your existing method.
While keeping sold books and books in separated tables is (IMO) good perfomance issue, I think you don't need to create separated IDENTICAL classes for them.
Consider making you're class BookDetails an abstract and annotating it as MappedSuperclass:
#MappedSuperclass
public abstract class BookDetails{
// fields
// getters
// setters
}
#Entity
#Table(name="SoldBooks")
public class SoldBookDetails extends BookDetails{
// Currently blank
}
#Entity
#Table(name="BookDetails")
public class TradingBookDetails extends BookDetails{
// Currently blank
}
While currently you're classes are identical, at future you may decide to create others book types (like other table and classes for purchasing books to store or books in the way to customer) and, of course, there may appear different logic for SoldBooks and others, and in this case such 'abstraction' will simplify maintenance.
The only changes to you're saveSoldBook I currently see is to change it's argument type or provide type check in the body of the method, as long as while argument type is BookDetails, you can pass in the function any variable, derived from it - therefore, TraidingBookDetails, SoldBookDetails etc. (Changes needed depends on you're logic in this method and DAO itself).

Avoid having JPA to automatically persist objects

Is there any way to avoid having JPA to automatically persist objects?
I need to use a third party API and I have to pull/push from data from/to it. I've got a class responsible to interface the API and I have a method like this:
public User pullUser(int userId) {
Map<String,String> userData = getUserDataFromApi(userId);
return new UserJpa(userId, userData.get("name"));
}
Where the UserJpa class looks like:
#Entity
#Table
public class UserJpa implements User
{
#Id
#Column(name = "id", nullable = false)
private int id;
#Column(name = "name", nullable = false, length = 20)
private String name;
public UserJpa() {
}
public UserJpa(int id, String name) {
this.id = id;
this.name = name;
}
}
When I call the method (e.g. pullUser(1)), the returned user is automatically stored in the database. I don't want this to happen, is there a solution to avoid it? I know a solution could be to create a new class implementing User and return an instance of this class in the pullUser() method, is this a good practice?
Thank you.
Newly create instance of UserJpa is not persisted in pullUser. I assume also that there is not some odd implementation in getUserDataFromApi actually persisting something for same id.
In your case entity manager knows nothing about new instance of UserJPA. Generally entities are persisted via merge/persist calls or as a result of cascaded merge/persist operation. Check for these elsewhere in code base.
The only way in which a new entity gets persisted in JPA is by explicitly calling the EntityManager's persist() or merge() methods. Look in your code for calls to either one of them, that's the point where the persist operation is occurring, and refactor the code to perform the persistence elsewhere.
Generally JPA Objects are managed objects, these objects reflect their changes into the database when the transaction completes and before on a first level cache, obviously these objects need to become managed on the first place.
I really think that a best practice is to use a DTO object to handle the data transfering and then use the entity just for persistence purposes, that way it would be more cohesive and lower coupling, this is no objects with their nose where it shouldnt.
Hope it helps.

How to create this model for Struts MVC?

I have a college management portal. I have to create the following classes for depicting the model.
class Address
{
String street;
String city;
}
class Contact
{
String phone;
String mobile;
}
abstract class Person
{
String name;
String age;
Address address;
Contact contact;
}
class Student extends Person
{
String course;
String stream;
String rollno;
}
class Faculty extends Person
{
String department;
String faculty id;
}
Now should i use the getter-setter methods for instance initialisation or constructors ?
What about the aggregation in class Person ??
How should the constructor work there ??
Yes I think you should have getter & setter methods for the model objects. Your attributes of the class should be made private.
The constructors are used to allow the mandatory information to be passed for object construction without which the object cannot be build (or the object is useless). Its like you cant create a person without name & age. In your case the address & contact many be optional. So you can set the address/contact information using mutator methods.
As Srinivas mentioned the constructors are not the alternatives for mutator method.
The purpose of constructor is make mandatory things available for object construction. Its like without raw material you cant build a building.
For this stuff these you need "beans" = private member variables with getters and setters for each. Depending on your needs you could create a constructor that has certain parameters to be set in the object at instantiation but also through the setters not directly (as certain setters might operate on the set value in a certain way so it is best that you do not mess up directly with stuff like this.student = "name").
For the faculty case I do not see why it extends Person and I do not think it should. As you say these are models they should reflect structures of tables in a database so at most each of them would extend an abstract class or implement a certain interface but not each other.
For the person aggregation also I believe that Contact And Address should be Integers as they represent a Foreign Key in another table and think about the case of many-to-many relation.
Models are first of all a reflection of the database in the application.

Categories

Resources