DAOs

  • Create typed and specific DAOs.

For example, while running named queries, call specifc dao methods even for named queries. OfficeDao.findOfficeById() is cleaner and easier to understand. You may still want to leverage a common code. For that, you can use an AOP advisor, to easily intercept such calls to delegate to a common method, while still scope for custom implementation if anyone so wants to override OfficeDao. At the same time, <X>Dao can also leverage AOP Proxy of a generic implementation for persistence. In general, rely on GenericDao for all persistence. see. org.mifos.accounts.fees.servicefacade.GenericDao You should however declare an interface for entity persistence for strong-typing. :

public interface GenericDao<T, ID extends Serializable> {
  T getDetails(ID id);
  List<T> getDetailsAll();
  void add(T newInstance);
  ID create(T newInstance);
  void update(T transientObject);
  void delete(T persistentObject);
  void saveOrUpdateAll(Collection<T> c);
}

the above probably are the most common persistent apis you would need. Now introduce a strongly typed DAO for entity. :

public interface FeeDao extends GenericDao<FeeEntity, Short> { }

So, do you need to write implementation of this DAO? Not at all. Most of the persistence are accomplished by GenericDaoHibernateImpl class. And you can set up a proxy for it. Check FeeContext.xml. for example:

<bean id="feeDao" parent="abstractDao">
     <property name="proxyInterfaces" value="org.mifos.accounts.fees.persistence.FeeDao"/>
     <property name="target">
         <bean parent="abstractDaoTarget">
            <constructor-arg>
              <value>org.mifos.accounts.fees.entities.FeeEntity</value> 
            </constructor-arg>
         </bean>
     </property>
  </bean>

This tells spring container, that feeDao is actually a proxied interface. Note: it takes a constructor arguement for the entity that you want to operate on. You should always use the strongly-typed entity dao. This allows others to implement the DAO without relying on GenericDao. If you require just persistence, just the marker interface (but typed) will do.

But you possibly require many read only queries, which in mifos codebase are as namedQueries. So, assuming, you require to retrieve all customer fees, you can define a namedQuery using JPA annotations in FeeEntity.java :

@NamedQuery(name="FeeEntity.retrieveCustomerFees",
  query="from FeeEntity fee where fee.categoryType.id in (1,2,3,4) order by fee.feeName"
)

You extend your FeeDao as such:

public interface FeeDao extends GenericDao<FeeEntity, Short> {
   List<FeeEntity> retrieveCustomerFees();
}

Basically, if you would need specific read-only-queries, (like named queries), explicitly introduce a method by the same named query signature. for example, if I needed a to query for a fee with category type = ? and fee name = ?, I would probably write a named query like:

@NamedQuery(
  name="FeeEntity.retrieveCustomerFeesByCategoryAndName",
   query="from FeeEntity fee where fee.categoryType.id =:categoryId and fee.feeName = :feename order by fee.feeName"
 )

And then go and introduce another method in FeeDao. :

public interface FeeDao extends GenericDao<FeeEntity, Short> {
  List<FeeEntity> retrieveCustomerFees();
  List<FeeEntity> retrieveCustomerFeesByCategoryAndName(Short categoryId, String feename);
}

Notice: how the method signature and parameter names match the named query syntax?

All <X>Persistence (derivative of org.mifos.framework.persistence.Persistence) should be converted to DAOs.

TODO: Technical Debts