Mapping a JDBC ResultSet to an object Mapping a JDBC ResultSet to an object mysql mysql

Mapping a JDBC ResultSet to an object


If you don't want to use any JPA provider such as OpenJPA or Hibernate, you can just give Apache DbUtils a try.

http://commons.apache.org/proper/commons-dbutils/examples.html

Then your code will look like this:

QueryRunner run = new QueryRunner(dataSource);// Use the BeanListHandler implementation to convert all// ResultSet rows into a List of Person JavaBeans.ResultSetHandler<List<Person>> h = new BeanListHandler<Person>(Person.class);// Execute the SQL statement and return the results in a List of// Person objects generated by the BeanListHandler.List<Person> persons = run.query("SELECT * FROM Person", h);


No need of storing resultSet values into String and again setting into POJO class. Instead set at the time you are retrieving.

Or best way switch to ORM tools like hibernate instead of JDBC which maps your POJO object direct to database.

But as of now use this:

List<User> users=new ArrayList<User>();while(rs.next()) {   User user = new User();         user.setUserId(rs.getString("UserId"));   user.setFName(rs.getString("FirstName"));  ...  ...  ...  users.add(user);} 


Let's assume you want to use core Java, w/o any strategic frameworks. If you can guarantee, that field name of an entity will be equal to the column in database, you can use Reflection API (otherwise create annotation and define mapping name there)

By FieldName

/**Class<T> clazz - a list of object types you want to be fetchedResultSet resultSet - pointer to your retrieved results */    List<Field> fields = Arrays.asList(clazz.getDeclaredFields());    for(Field field: fields) {        field.setAccessible(true);    }    List<T> list = new ArrayList<>();     while(resultSet.next()) {        T dto = clazz.getConstructor().newInstance();        for(Field field: fields) {            String name = field.getName();            try{                String value = resultSet.getString(name);                field.set(dto, field.getType().getConstructor(String.class).newInstance(value));            } catch (Exception e) {                e.printStackTrace();            }        }        list.add(dto);    }

By annotation

@Retention(RetentionPolicy.RUNTIME)public @interface Col {    String name();}

DTO:

class SomeClass {   @Col(name = "column_in_db_name")   private String columnInDbName;   public SomeClass() {}   // ..}

Same, but

    while(resultSet.next()) {        T dto = clazz.getConstructor().newInstance();        for(Field field: fields) {            Col col = field.getAnnotation(Col.class);            if(col!=null) {                String name = col.name();                try{                    String value = resultSet.getString(name);                    field.set(dto, field.getType().getConstructor(String.class).newInstance(value));                } catch (Exception e) {                    e.printStackTrace();                }            }        }        list.add(dto);    }

Thoughts

In fact, iterating over all Fields might seem ineffective, so I would store mapping somewhere, rather than iterating each time. However, if our T is a DTO with only purpose of transferring data and won't contain loads of unnecessary fields, that's ok. In the end it's much better than using boilerplate methods all the way.

Hope this helps someone.