Data Access Object

A Data Access Object handles domain objects. The main purpose of these objects is to simplify, encapsulate, and concentrate all database activity for domain objects, and for the system in general.

Defining a DAO

To define a DAO you must implement the Dao Interface, define it as a Spring bean. There is no need to implement the DAO class yourself, unless you are doing something truely extra-ordinary.

Defining a DAO in Spring

The framework defines a parent DAO spring bean. Extend this bean to define your own DAO. This parent bean is really a proxy factory bean, which creates a proxy object for your DAO interface. In simpler words - it implements your interface to a concrete class at runtime (and yes the performance is just fine).

For example:

 <bean parent="dao" id="employeeDao">
   <property name="daoInterface"
          value="net.sf.shineframework.demoapp.bl.dao.EmployeeDao" />
 </bean>

The above example creates a DAO for the EmployeeDao interface. The interface should extend one of the framework DAO interfaces:

  • Dao - this is the parent for all other DAO interfaces, it defines the basic DAO operations.
  • NamedDao - a convenience interface that defines a DAO for objects with the property "name", which is very common.

These DAO interfaces are generic types. Your custom DAO should pass the class of the domain object the DAO manages to the parent interface. For example:

 public interface EmployeeDao extends NamedDao<Employee> {
   ...
 }

The contents of your custom DAO should only be getter methods. These methods translate to queries at runtime. There are several kinds of queries that can be generated from the DAO:

  • Named-query-based queries - queries that run a named query defined on the domain object.
  • Property-based queries - queries based on property or properties of the domain object.

For the next example suppose the Employee domain object has a named query called "Employee.ByMinSalary":

 // example of a named-query based runtime generated method
 public Collection<Employee> getByMinSalary(@QueryParam("minSal") double minSal) throws DataAccessException;

The generated runtime proxy for this method will run the "Employee.ByMinSalary" query and pass it the parameters defined in the method signature. However, in order for the framework to support named params in the named query (which is a good programming practice), the programmer must supply the name of the named param using the parameter-level annotation @QueryParam.

Now for this example suppose the Employee domain object does not have a named query called "Employee.ByEmpno", and that the Employee domain object does have a property called empno:

 // example of a property based runtime generated method
 public Employee getByEmpno(int empno) throws DataAccessException;

This time, since the "Employee.ByEmpno" named query does not exist, the runtime proxy will try to run a property-based query and match the parameter passed to the method to the empno property of Employee.

Using the DAO supplied methods

The framework DAO supplies several methods (see javadoc for details). Amongst them these are worth mentioning in details:

  • Get by properties - retrieve objects by an example domain object.
  • Get by unique properties - retrieve objects by unique properties and an example domain object.
  • Get by business key - retrieve objects by their business key.

An example domain object is a domain object of the type managed by the specific DAO, with properties set on it as an example for the query.

Get By Properties

The Dao.getByProperties method retrieves a domain object by an example domain object using named properties. For example - the Employee domain object has the following properties: empno, name, salary, department. Suppose we want to fetch all employees named John with the salary 100.0. We need to create the example domain object:

 Employee example=new Employee();
 example.setName("John");
 example.setSalary(100.0);

Then query with it:

 EmployeeDao employeeDao=(EmployeeDao)context.getBean("employeeDao");
 Collection<Employee> result=employeeDao.getByProperties(example,"name","salary");

Yes, I realize this example makes little business sense, but it's just an example!

Get By Unique Properties

The Dao.getByUniqueProperties method returns a single domain object and not a collection like the Dao.getByProperties method. The runtime proxy dao in this case reflects upon the DAO managed domain object, and finds all columns with the unique marker set to true. With that a simple property by example query is activated.

Get By Business Key

Much like the Dao.getByUniqueProperties method this method reflects the managed domain object and searches for business key properties. All these properties should have a non-null value in the example domain object.

Programming Conventions

  • All DAOs should be defined as an interface and an implementation class.
  • The interface must extend the Dao interface.
  • Your DAO interface should be placed in a package called: net.sf.shineframework.XXX.dal.dao whereas XXX is the name of your project.