Populating JavaBeans from Database Values
July 19, 2002 Timothy Prickett Morgan
Hey, David:
I am trying to build my first database inquiry Servlet using Java and Tomcat. I defined my screen in a Java class and use another Java class to retrieve the database values. When I display the screen, I end up with a lot of statements that set a value using the corresponding getter from the database class. Those calls look like this example:
SetCustomer(getCustomer()); SetCustomerName(getCustomerName());
Before I start using this program as a base for another Servlet, I would like to eliminate these calls. Do you have any ideas how I would do this?
— Sean
|
I can think of two ways to make it easier to adapt your program to work with other files. The first way, which is the most flexible, would be to store your values in a Map. A Map is a type of Collection that stores key/value pairs; in this case, the key would be the column name (also known as field name), and the value would be the column’s value. The second way to make your program more adaptable is to use reflection to locate getter/setter pairs.
Since you didn’t send any code, I can’t give you a specific solution, but I can give you some general examples. I use a method like the following example to store a record’s values in a Map:
/** * Method convert result set to collection containing * two dimensional collection of rows and columns. This * method allows a map to be specified for columns, * which is keyed by the column name. * @param rs * @param rowsCol * @param columnsMap * @param string Force all columns returned to string. * @return Collection */ public static Collection convert( ResultSet rs, Collection rowsCol, Map columnsMap, boolean string) { Collection rows = null; if (rs != null) { try { Class clazz = rowsCol.getClass(); rows = (Collection) clazz.newInstance(); clazz = columnsMap.getClass(); Object clm = null; Map clms = null; ResultSetMetaData rsmd = null; rsmd = rs.getMetaData(); int clmCnt = rsmd.getColumnCount(); while (rs.next()) { clms = (Map) clazz.newInstance(); for (int i = 1; i <= clmCnt; i++) { if (string) { clm = rs.getString(i); } else { clm = rs.getObject(i); } clms.put( new String( rsmd.getColumnName(i).toLowerCase()), clm); } rows.add(clms); } } catch (Exception ex) { ex.printStackTrace(); } } return rows; }
The convert method takes an SQL result set into a Collection of Rows. Each row contains a Map of column names and values. To call this method, you would pass the ResultSet to convert, the type of row Collection to return, the type of column Map to return, and a Boolean flag indicating whether to convert the results to a String.
To be more flexible, convert works with the base Collection and Map classes. There are many implementations of Collection and Map, for example Vector, ArrayList, HashMap, and TreeMap. The best implementation will be dependent on the application. For this reason, the method in this example lets the caller pass in the type. In most cases an ArrayList and HashMap are appropriate. An alternative to this approach would be to pass a factory object to the convert method that returned the appropriate types.
If you decide that storing your database values in a Map doesn’t make sense, you can use reflection to match getter and setter pairs. The code to do this can get quite complicated, particularly when your class contains nested objects. You might want to look at a set of open source classes that, like Tomcat, are distributed by the Apache Software Foundation. Those classes are the BeanUtils and are a part of the Jakarta Commons project.
The following example adapts the convert method from the first example so that it will set column properties contained in a JavaBean. In this example, a map of column name and value pairs is passed to the BeanUtils.populate method, which then calls the setter associated with each column.
/** * Method convert result set to collection containing * two dimensional collection of rows containing a * bean representing the columns. The bean properties * are set based on the column names associated with * the result set. * @param rs * @param rowsCol * @param columnsBean Cloneable objects will be * instantiated using clone method. * @param string Force all columns returned to string. * @return Collection */ public static Collection convert( ResultSet rs, Collection rowsCol, Object columnsBean, boolean string) { Collection rows = null; if (rs != null) { try { Class clazz = rowsCol.getClass(); rows = (Collection) clazz.newInstance(); // Setup columns for clone if possible class ColumnsBeanClone implements Cloneable { public Object clone() { return new Object(); } } ColumnsBeanClone clmsClone = null; boolean clone = false; boolean pool = false; if (columnsBean instanceof Cloneable) { clone = true; clmsClone = (ColumnsBeanClone) columnsBean; } else { clazz = columnsBean.getClass(); } Object clm = null; HashMap clms = null; Object clmsBean = null; ResultSetMetaData rsmd = null; rsmd = rs.getMetaData(); int clmCnt = rsmd.getColumnCount(); while (rs.next()) { clms = new HashMap(); for (int i = 1; i <= clmCnt; i++) { if (string) { clm = rs.getString(i); } else { clm = rs.getObject(i); } clms.put( new String(rsmd.getColumnName(i)), clm); } // Create new empty object if (clone) { clmsBean = clmsClone.clone(); } else { clmsBean = clazz.newInstance(); } // Set the corresponding properties of our bean BeanUtils.populate(clmsBean, clms); rows.add(clmsBean); } } catch (Exception ex) { ex.printStackTrace(); } } return rows; }
I hope these examples give you some ideas. Making your code more dynamic may take longer up front, but in the end will save you a lot of time.
— David
Sponsored By TRAMENCO |
The Training and Mentoring Company (Tramenco) is dedicated to just one thing: Advancing your career by giving you the skills you need to solve real-world business problems. Choose from a menu of training options to fit your needs: onsite seminars, public seminars, mentoring, consulting, books, CBTs, and Web-based training. For more information about Tramenco’s career enhancing opportunities, call (800)421-8031 or go to www.tramenco.com. |