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.
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.
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:
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:
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.
The framework DAO supplies several methods (see javadoc for details). Amongst them these are worth mentioning in details:
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.
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!
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.
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.