I have ValueObjects with injectors and selectors which I map to my
columns in my database, I have code written that automatically
populates my bean from a resultset:
public class DAOConvertor
{
/**
* <p>
* This converts a resultset into a value object dynamically via
the use
* of a set of bean-property / sql-column-name mappings.
* </p>
* @param a_Resultset Resultset used as the data source
* @param a_ColumnPropertyMap Map containing bean-property /
sql-column-name mappings.
* @param a_TargetValueObject Target value object to populate.
* @return Object A reference to the value object.
We have to use a return
* rather then rely on byRef because
this may be used
* in an EJB context. In this context
all results are
* byVal rather than byRef. Relying
on byRef is dangerous.
* @throws DAOException
*/
public static Object convert ( ResultSet a_Resultset, Map
a_ColumnPropertyMap, Object a_TargetValueObject )
throws DAOException
/*
-----------------------------------------------------------------------------
d1 26 Nov 03 Ben Jessel Created.
-----------------------------------------------------------------------------
*/
{
try
{
// Get an iterator to enable us to iterate through all
the properties
// in the hashmap.
Set stPropertyColumns = a_ColumnPropertyMap.keySet();
Iterator itPropertyColumns = stPropertyColumns.iterator();
// Iterate through each property / column-name pair
while ( itPropertyColumns.hasNext() )
{
// Get the next property
String nextKey = ( String ) itPropertyColumns.next();
// Get the SQL column corresponding to this property
// and query the resultset for the data in this column
Object obj = a_Resultset.getObject( ( String )
a_ColumnPropertyMap.get ( nextKey ) );
// Set the target object's property ( as pointed to by
the property
// key in the map ) with the data gleaned from the
resultset.
// As we are dealing with objects here, we let the
reflection
// API deal with type conversions.
BeanUtil.setProperty ( a_TargetValueObject, nextKey,
obj );
}
return a_TargetValueObject;
}
catch ( SQLException sql )
{
throw new DAOException ( sql );
}
catch ( AutoPopulationException ape )
{
throw new DAOException ( ape );
}
}
/**
* <p>Empty constructor</p>
*/
public DAOConvertor() {
super();
}
}
/*
*
* =============================================================================
*
* MobileInteractive Copyright (c) 2002
* <p>
* This code is copyright and should not be modified. Nor should the
* class files be decompiled, or recompiled with changed source
without
* the explicit permission from MobileInteractive.
* </p>
*
* Class Name : BeanUtil.java
*
* Log
* =============================================================================
* $Log$
*
*/
package com.mobileinteractive.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import com.mobileinteractive.exception.AutoPopulationException;
import com.mobileinteractive.exception.CheckedConfigurationException;
/**
* <P>
* Description : ++TO DO
* </P>
* @author $author$
* @version $revision$
*/
public class BeanUtil
{
public static final int SELECTORS = 1;
public static final int INJECTORS = 2;
public static final int INJECTORS_OR_SELECTORS = 3;
private BeanUtil() {}
//-- Constants -------------------------------------------------------------
public static final String c_ksClassName = "BeanUtil";
//-- Methods-- -------------------------------------------------------------
/**
* <p>
* This sets the property of the object supplied, with the
property and
* value supplied.
* </p>
* @param a_objTarget
* @param sPropertyField
* @param a_TargetValue
* @throws AutoPopulationException
*/
public static void setProperty ( Object a_objTarget, String
sPropertyField, Object a_TargetValue )
throws AutoPopulationException
/*
-----------------------------------------------------------------------------
d1 26 Nov 03 Ben Jessel Created.
-----------------------------------------------------------------------------
*/
{
final String ksLocation = "setProperty ( Object a_objTarget,
String sPropertyField, Object a_TargetValue )";
Map destProperties = getBeanProperties( a_objTarget, INJECTORS
);
try
{
// Can we find the property?
if ( destProperties.get( sPropertyField )!=null )
{
Object[] parameters = new Object [ 1 ] ;
parameters [ 0 ] = a_TargetValue;
( ( Method ) destProperties.get( sPropertyField )
).invoke ( a_objTarget, parameters );
}
else
{
throw new CheckedConfigurationException (
c_ksClassName + "." + ksLocation + " Cannot find field " +
sPropertyField);
}
}
catch ( InvocationTargetException ite )
{
throw new CheckedConfigurationException ( ite );
}
catch ( IllegalAccessException ile )
{
throw new CheckedConfigurationException ( ile );
}
}
/**
* <p>
* Populates a destination bean from a source bean.
* </p>
* @param a_Source
* @param a_Destination
* @return
*/
public static Object populate ( Object a_Source, Object
a_Destination )
{
Map srcProperties = getBeanProperties( a_Source, SELECTORS );
Map destProperties = getBeanProperties( a_Destination,
INJECTORS );
Iterator keySetIterator = srcProperties.keySet().iterator();
while ( keySetIterator.hasNext() )
{
String selectorKey = ( String ) ( keySetIterator.next()
);
Method selectorMethod = ( Method ) srcProperties.get(
selectorKey );
if ( destProperties.get( selectorKey )!=null )
{
Method injectorMethod = ( ( Method )
destProperties.get( selectorKey ) );
try
{
if ( injectorMethod.getParameterTypes().length ==
1 )
{
Object selectorResult[] = new Object[1];
selectorResult[0] = selectorMethod.invoke(
a_Source, null );
if (
injectorMethod.getParameterTypes()[0].isAssignableFrom(
selectorMethod.getReturnType()) )
{
// get the results from the selector
object
injectorMethod.invoke( a_Destination,
selectorResult );
}
else
{
if (
injectorMethod.getParameterTypes()[0].getName().equals(
"java.lang.String" ) )
{
Class clazz =
selectorMethod.getReturnType();
System.out.println(clazz.getName());
selectorResult[0] =
String.valueOf( selectorResult[0] );
injectorMethod.invoke(
a_Destination, selectorResult );
}
if (
injectorMethod.getParameterTypes()[0].getName().equals(
"java.lang.Long" ) )
{
Class clazz =
selectorMethod.getReturnType();
System.out.println(clazz.getName());
selectorResult[0] = Long.valueOf(
Sting.valueOf(selectorResult[0]) );
injectorMethod.invoke(
a_Destination, selectorResult );
}
if (
injectorMethod.getParameterTypes()[0].getName().equals( "long" ) )
{
Class clazz =
selectorMethod.getReturnType();
System.out.println(clazz.getName());
selectorResult[0] = Long.valueOf(
String.valueOf(selectorResult[0]==null ? "0" : selectorResult[0]) );
injectorMethod.invoke(
a_Destination, selectorResult );
}
if (
injectorMethod.getParameterTypes()[0].getName().equals( "int" ) )
{
Class clazz =
selectorMethod.getReturnType();
System.out.println(clazz.getName());
selectorResult[0] =
Integer.valueOf( String.valueOf(selectorResult[0]==null ? "0" :
selectorResult[0]) );
injectorMethod.invoke(
a_Destination, selectorResult );
}
if (
injectorMethod.getParameterTypes()[0].getName().equals( "byte" ) )
{
Class clazz =
selectorMethod.getReturnType();
System.out.println(clazz.getName());
selectorResult[0] = Byte.valueOf(
String.valueOf(selectorResult[0]==null ? "0" : selectorResult[0]) );
injectorMethod.invoke(
a_Destination, selectorResult );
}
if (
injectorMethod.getParameterTypes()[0].getName().equals( "float" ) )
{
Class clazz =
selectorMethod.getReturnType();
System.out.println(clazz.getName());
selectorResult[0] = Float.valueOf(
String.valueOf(selectorResult[0]==null ? "0" : selectorResult[0]) );
injectorMethod.invoke(
a_Destination, selectorResult );
}
if (
injectorMethod.getParameterTypes()[0].getName().equals( "double" ) )
{
Class clazz =
selectorMethod.getReturnType();
System.out.println(clazz.getName());
selectorResult[0] = Float.valueOf(
String.valueOf(selectorResult[0]==null ? "0" : selectorResult[0]) );
injectorMethod.invoke(
a_Destination, selectorResult );
}
if (
injectorMethod.getParameterTypes()[0].getName().equals( "char" ) )
{
// ??
}
if (
injectorMethod.getParameterTypes()[0].getName().equals(
"java.util.Date" ) )
{
selectorResult[0] = new Date(
String.valueOf(selectorResult[0]==null ? "" : selectorResult[0]) );
injectorMethod.invoke( a_Destination,
selectorResult );
}
}
}
}
catch (InvocationTargetException ite ) {}
catch (IllegalAccessException iea) {}
}
}
return a_Destination;
}
/**
* <p>
* This gets the bean properties for a supplied bean.
* A map is constructed where the key is the property name ( the
method
* name minus the starting set/get ). The value is the method
itself.
* This means that we can have fast searching by property name
on the key
* as well as quick method parameter type / return type.
* The options for the <code>a_PropertyType</code> are:
* <ul>
* <li> 1 - get SELECTOR bean properties. </ul>
* <li> 2 - get INJECTOR bean properties. </ul>
* </ul>
* Injector properties must have only one parameter.
* Selectors must have a non-void return type.
* </p>
* @param a_Bean
* @param a_PropertyType
* @return
*/
public static Map getBeanProperties ( Object a_Bean, int
a_PropertyType )
/*
---------------------------------------------------------------------------
d1 08 Sept 02 Ben Jessel Created.
---------------------------------------------------------------------------
*/
{
// get all the methods for this class
Method[] beanMethods = a_Bean.getClass().getMethods();
Map propertyMap = new HashMap();
for ( int i=0; i<beanMethods.length; i++ )
{
if ( ( a_PropertyType == SELECTORS ) &&
( beanMethods [ i ].getName().startsWith( "get" ) ) )
{
if ( !beanMethods [ i
].getReturnType().getName().equals("void"))
{
// Get the name of this method, and remove the
"get" to just
// give a property name
String propertyName = beanMethods [ i
].getName();
propertyName = propertyName.substring(
propertyName.indexOf("get")+3 );
propertyMap.put ( propertyName, beanMethods [ i ]
);
}
}
else if ( ( a_PropertyType == INJECTORS ) &&
( beanMethods [ i ].getName().startsWith( "set" ) ) )
{
if ( beanMethods [ i
].getParameterTypes().length==1 )
{
// Get the name of this method, and remove the
"set" to just
// give a property name
String propertyName = beanMethods [ i
].getName();
propertyName = propertyName.substring(
propertyName.indexOf("set")+3 );
propertyMap.put ( propertyName, beanMethods [ i
] );
}
}
}
return propertyMap;
}
}
Jose Rubio said:
Option #1 is better. You're describing what is called the Value Object
pattern. You'll see these classes called something like CustomerVO.
then the JDBC access classes are what you called DAOs. Those classes can
instantiate the VOs with the data. This aproach is better because you can
pass the VO objects around, they can be auto generated fromt he database
structures, and the can be serialized.
Hope it helps,
Jose
f said:
Hi,
Suppose I have tables in database,
Customer table with columns like customer ID, name, address...
Order table with columns like order ID, prices, total...
I am now writing java code to access database. I am thinking about two
approaches,
1. Define class like
class Customer{
int ID;
String name;
....
}
class Order{
int ID;
double price;
...
}
and write JDBC code to access database and fill these class
objects. I probably can use some code generation tool to write the
code. Or maybe even JDO?
2. Write a universal class
class Data{
String[] names;
....
int getIntColumn(String name);
double getDoubleColumn(String name);
static Data queryDatabase(String tableName, String[] columns,
String where);
};
and write JDBC code to access database and fill the data. I need
only wirte one class, and it works for any table or view for query.
Which is better?
Thanks,
ff