<beans>
<bean id="userDAO" class="GenericDAO" />
<bean id="userService" class="UserService">
<property name="dao">
<ref bean="userDAO" />
</property>
</bean>
</beans>
Then to get a User record from your UserDAO inside your UserService, your code might look like:
component {
public any function get(string id) {
return getDAO().get("User",id);
}
}
While this works, it seems a little weird having to pass in the name of the entity to the DAO. Ideally the code would simply be:
component {
public any function get(string id) {
return getDAO().get(id);
}
}
I decided to play around a little bith with the code and was able to accomplish this with the help of ColdSpring. Rather than having my userDAO point directly to the GenericDAO class, I've created a DAOFactory instead to generate an instance of a DAO. Here's what my config looks like:
<beans>
<bean id="userDAO" factory-bean="daoFactory" factory-method="getUserDAO" />
<bean id="daoFactory" class="DAOFactory">
<constructor-arg name="class">
<value>GenericDAO</value>
</constructor-arg>
</bean>
<bean id="userService" class="UserService">
<property name="dao">
<ref bean="userDAO" />
</property>
</bean>
</beans>
Here's what my DAOFactory.cfc looks like:
component extends="SingletonFactory" {
public any function init(string class) {
return super.init("dao",class);
}
public any function onMissingMethod(string missingMethodName, struct missingMethodArguments) {
var object = getObject();
object.entityName = getEntityName(missingMethodName);
return object;
}
}
Here's what SingletonFactory.cfc looks like, which the DAOFactory extends:
component {
public any function init(string type, string class) {
variables.type = type;
variables.class = class;
return this;
}
private any function getObject() {
return createObject("component",variables.class);
}
private string function getEntityName(string methodName) {
methodName = replaceNoCase(methodName,"get","");
return left(methodName,len(methodName)-len(variables.type));
}
public any function onMissingMethod(string missingMethodName, struct missingMethodArguments) {
return getObject();
}
}
Finally, here's what my GenericDAO.cfc looks like:
component {
this.entityName = "";
public array function list(string criteria, array params) {
var hql = "from " & this.entityName;
if (structKeyExists(arguments,"criteria")) {
hql = hql & " where " & criteria;
}
if (structKeyExists(arguments,"params")) {
return ormExecuteQuery(hql,params);
}
return ormExecuteQuery(hql);
}
public any function get(string id) {
return entityLoad(this.entityName, id);
}
public void function save(any entity) {
entitySave(entity);
}
public void function delete(any entity) {
entityDelete(entity);
}
}
Taking this one step further, you could use the same idea and create really simple Services using a ServiceFactory.
Here's what your coldspring.xml might look like:
<beans>
<bean id="userDAO" factory-bean="daoFactory" factory-method="getUserDAO" />
<bean id="daoFactory" class="DAOFactory">
<constructor-arg name="class">
<value>GenericDAO</value>
</constructor-arg>
</bean>
<bean id="userService" factory-bean="serviceFactory" factory-method="getUserService">
<property name="dao">
<ref bean="userDAO" />
</property>
</bean>
<bean id="serviceFactory" class="ServiceFactory">
<constructor-arg name="class">
<value>GenericService</value>
</constructor-arg>
</bean>
</beans>
Here's what the ServiceFactory.cfc looks like:
component extends="SingletonFactory" {
public any function init(string class) {
return super.init("service",class);
}
}
And here's GenericService.cfc:
component {
public void function setDAO(any dao) {
variables.dao = arguments.dao;
}
private string function getDAO() {
return variables.dao;
}
public array function list(string criteria, array params) {
if(!StructKeyExists(arguments,"criteria")){
arguments.criteria = "";
}
if(!StructKeyExists(arguments,"params")){
arguments.params = [];
}
return getDAO().list(criteria,params);
}
public any function get(string id) {
return getDAO().get(id);
}
public any function save(any entity) {
return getDAO().save(entity);
}
public any function delete(any entity) {
return getDAO().delete(entity);
}
}
I took most of this code from Joe's example, but just shrunk it down a little bit for the sake of the post. Also, I haven't hooked this up to a database to test it, so there might be some syntax errors. Finally, I wrote this during a rather boring session at MAX, so I'll admit there's a lot of rambling going on. Hopefully you can kind of follow the logic.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.