What is the correct way to initialize an object collection (POJO) in a Spring-Hibernate project?

I have a POJO class, say Foo, which has a set of other entity instances, like bars. There are also standard classes for such a project: service and dao for Foo and Bar.

I want BarService to receive instances of a set of bars associated with some Foo. Now I have the following code, which I think is conceptually bad.

public class Foo { Set<Bar> bars; public Set<Bar> getBars() { if (bars == null) return ( bars = new HashSet() ); return bars; } } 
 public class BarServiceImpl { public List<Bar> getListOfBars(Foo foo) { return new ArrayList(foo.getBars()); } } 

3 questions: Where is it better to initialize the Foo Set? What specific sets and lists are best for such purposes? What conceptual problems have my current implementation and how to do better?

Thanks in advance.

+6
java spring collections architecture hibernate
source share
3 answers

Your organization can be a simple set of fields with getters and setters. What you need to take care of is how you link your objects and use them to populate the objects.
ORM APIs provide the freedom to use objects, not SQL. You must be careful when you must choose to initialize the fields of an object. For example, if you have an entity’s face that includes a name, age, collection of contacts and visited cities. In a situation where you are interested in the name and age of the person, not the contact and the city, you should only download the name and age. This means that contacts and cities must be lazy loaded. When you are interested in a contact, you download only the contacts, not the entire entity of the person or through the entity of the person. You want to download a set of contacts using Dao / Service only and explicitly define methods for loading a specific aspect of an object (using feedback).
Some best hibernation techniques can be found at Best Practices . Updated: 1) The essence is not filled by itself. One popular approach is to provide a DAO for this assignment. Your organization may be simple.

 public class Foo { private Set<Bar> bar=new HashSet<Bar>(); public Set<Bar> getBar { return bar; } public void setBar(Bar bar) { this.bar = bar; } } 

2) You can manage transactions at another level, also called the service level.

+2
source share

Where is better to initialize Foo Set?

In most cases, I initialize collections when they are declared, which is what Hibernate recommends. Indication of documentation:

6.1. Persistent collections

Hibernation requires persistent declared fields containing data as an interface type. For example:

 public class Product { private String serialNumber; private Set parts = new HashSet(); public Set getParts() { return parts; } void setParts(Set parts) { this.parts = parts; } public String getSerialNumber() { return serialNumber; } void setSerialNumber(String sn) { serialNumber = sn; } } 

The actual interface could be java.util.Set java.util.Collection java.util.List , java.util.Map , java.util.SortedSet java.util.SortedMap or anything you like ("whatever you like "means you will have to write an implementation from org.hibernate.usertype.UserCollectionType .)

Notice how the instance variable was initialized by the HashSet instance. This is the best way to initialize the property collection of new instances of (mutable) instances. When you make an instance persistent by calling persist() , for example, Hibernate will actually replace the HashSet with the Hibernate instance of its own implementation of Set .

If leaving it null is part of your company, my suggestion would be to initialize it in general link management methods:

 public class Foo { ... private Set<Bar> bars; ... public void addBar(Bar bar) { if (this.bars == null) { this.bars = new HashSet<Bar>(); } this.bars.add(bar); } } 

What specific sets and lists are best for these purposes?

It all depends on the semantics that you need. A Set does not allow duplication, a List allows duplication and introduces positional indexing.

What conceptual problems have my current implementation and how to do better?

  • I would not do the job in getter.
    • If at this point the collection should be null , let it be null .
  • I do not see the added value of your service
    • why not just call foo.getBars() ?
    • why convert a collection?
+11
source share

i tend to initialize collections at the service level, where I also save transaction processing. That way, I can have a method in my BaseDAO that allows me to initialize any collection of any Entity in my projects using reflection, passing the collection names to a method that should be looked forward to (initialized):

 public <T extends Object> T getEntity(Class<T> clazz,long id,String[] collectionsToBeInitialized){ T entity=(T) this.getCurrentSession().createCriteria(clazz).add(Restrictions.idEq(id)).setFetchMode(collectionsToBeInitialized[0], FetchMode.JOIN).uniqueResult(); int length=collectionsToBeInitialized.length; for (int idx=1;idx<length;idx++){ String collectionName=collectionsToBeInitialized[idx]; try { Method m = clazz.getMethod("get" + collectionName.substring(0, 1).toUpperCase() + collectionName.substring(1),(Class<T>) null); Hibernate.initialize(m.invoke(entity,(Object[]) null)); } catch (NoSuchMethodException e) { LOG.error("Could not initialize collection " + collectionName + " of class Event", e); } catch (InvocationTargetException e) { LOG.error("Could not initialize collection " + collectionName + " of class Event", e); } catch (IllegalAccessException e) { LOG.error("Could not initialize collection " + collectionName + " of class Event", e); } } return entity; } 

then you can initialize any collection from the service level using this method:

 MyEntity ent=getEntity(MyEntity.class,id,new String[]{"collection1","collection2"}); 

More detailed example: http://objecthunter.congrace.de/tinybo/blog/articles/69

+1
source share

All Articles