{"id":900,"date":"2014-01-14T21:25:54","date_gmt":"2014-01-14T20:25:54","guid":{"rendered":"http:\/\/oprsteny.cz\/?p=900"},"modified":"2014-01-14T21:25:54","modified_gmt":"2014-01-14T20:25:54","slug":"java-map-resultset-to-object-dynamically","status":"publish","type":"post","link":"https:\/\/oprsteny.cz\/?p=900","title":{"rendered":"Java &#8211; Map ResultSet to Object dynamically"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"897\" data-permalink=\"https:\/\/oprsteny.cz\/?attachment_id=897\" data-orig-file=\"https:\/\/oprsteny.cz\/wp-content\/uploads\/eclipse.png\" data-orig-size=\"44,42\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"Java\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/oprsteny.cz\/wp-content\/uploads\/eclipse.png\" class=\"size-full wp-image-897 alignleft\" alt=\"Java\" src=\"http:\/\/oprsteny.cz\/wp-content\/uploads\/eclipse.png\" width=\"44\" height=\"42\" \/>Did you ever wanted \u00a0to implement simple mapping of database tables to java objects (models) and you wanted to do the whole stuff dynamically? I managed to put some code together which does exactly what you wanted<!--more--><\/p>\n<p>At first I created a model class in Java reflecting one database table. I used annotations to specify that the class is an <em>Entity <\/em>and the table fields modeled in the class are <em>Columns. <\/em>These annotations are available in Java SDK packages<em> javax.persistence.Column <\/em>and<em> javax.persistence.Entity. <\/em>But I also wanted to play with annotations so I created them myself:<\/p>\n<pre lang=\"java\">@Target(ElementType.TYPE)\r\n@Retention(RetentionPolicy.RUNTIME)\r\npublic @interface Entity {\r\n}<\/pre>\n<pre lang=\"java\">@Target(ElementType.FIELD)\r\n@Retention(RetentionPolicy.RUNTIME)\r\npublic @interface Column {\r\n  String name() default \"\";\r\n}<\/pre>\n<p>As an example of database table\/java model I&#8217;ll use DB table<em> Accounts <\/em>(columns <em>ID, Name, IsActive<\/em>)\u00a0with its corresponding Java model class<em> Account<\/em>:<\/p>\n<pre lang=\"java\">@Entity\r\npublic class Account {\r\n  @Column(name=\"ID\")\r\n  private int id;\r\n\r\n  @Column(name=\"Name\")\r\n  private String name;\r\n\r\n  @Column(name=\"IsActive\")\r\n  private String isActive;\r\n\r\n  @Override\r\n  public String toString() {\r\n    return \"ID: \" + id + \"\\n\" +\r\n    \"Name: \" + name + \"\\n\"+\r\n    \"Active: \" + isActive + \"\\n\\n\";\r\n  }\r\n}<\/pre>\n<p>Now comes the most interesting part where database ResultSet is mapped to an Object. This is encapsulated in separate class called<em> ResultSetMapper<\/em><\/p>\n<pre lang=\"java\">public class ResultSetMapper&lt;T&gt; {\r\n\/\/ This method is already implemented in package \r\n\/\/ but as far as I know it accepts only public class attributes\r\n  private void setProperty(Object clazz, String fieldName, Object columnValue) {\r\n    try {\r\n      \/\/ get all fields of the class (including public\/protected\/private)\r\n      Field field = clazz.getClass().getDeclaredField(fieldName);\r\n      \/\/ this is necessary in case the field visibility is set at private\r\n      field.setAccessible(true);\r\n      field.set(clazz, columnValue);\r\n    } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {\r\n      e.printStackTrace();\r\n    }\r\n  }\r\n\r\n  @SuppressWarnings({ \"unchecked\", \"rawtypes\" })\r\n  public List&lt;T&gt; mapRersultSetToObject(ResultSet rs, Class clazz) {\r\n    List&lt;T&gt; outputList = null;\r\n    try {\r\n      \/\/ make sure resultset is not null\r\n      if (rs != null) {\r\n\r\n        \/\/ check if Class clazz has the 'Entity' annotation\r\n        if (clazz.isAnnotationPresent(Entity.class)) {\r\n\r\n          \/\/ get the resultset metadata\r\n          ResultSetMetaData rsmd = rs.getMetaData();\r\n\r\n          \/\/ get all the attributes of Class clazz\r\n          Field[] fields = clazz.getDeclaredFields();\r\n\r\n          while (rs.next()) {\r\n            T bean = (T) clazz.newInstance();\r\n            for (int _iterator = 0; _iterator &lt; rsmd.getColumnCount(); _iterator++) {\r\n              \/\/ get the SQL column name\r\n              String columnName = rsmd.getColumnName(_iterator + 1);\r\n\r\n              \/\/ get the value of the SQL column\r\n              Object columnValue = rs.getObject(_iterator + 1);\r\n\r\n              \/\/ iterating over clazz attributes to check \r\n              \/\/ if any attribute has 'Column' annotation with matching 'name' value\r\n              for (Field field : fields) {\r\n                if (field.isAnnotationPresent(Column.class)) {\r\n                  Column column = field.getAnnotation(Column.class);\r\n                  if (column.name().equalsIgnoreCase(columnName) \r\n                      &amp;&amp; columnValue != null) {\r\n                    this.setProperty(bean, field.getName(), columnValue);\r\n                    break;\r\n                  }\r\n                }\r\n              } \/\/ EndOf for(Field field : fields)\r\n            } \/\/ EndOf for(_iterator...)\r\n            if (outputList == null) {\r\n              outputList = new ArrayList&lt;T&gt;();\r\n            }\r\n            outputList.add(bean);\r\n          } \/\/ EndOf while(rs.next())\r\n        } else {\r\n          \/\/ throw some error that Class clazz \r\n          \/\/ does not have @Entity annotation\r\n        }\r\n      } else {\r\n        \/\/ ResultSet is empty\r\n        return null;\r\n      }\r\n    } catch (IllegalAccessException e) {\r\n      e.printStackTrace();\r\n    } catch (SQLException e) {\r\n      e.printStackTrace();\r\n    } catch (InstantiationException e) {\r\n      e.printStackTrace();\r\n    }\r\n\r\n    return outputList;\r\n  }\r\n}<\/pre>\n<p>To test if this mapper works if we will connect to database, read some data and print it out:<\/p>\n<pre lang=\"java\">public class Main {\r\n  public static void main(String[] args) throws ClassNotFoundException {\r\n    Connection con = null;\r\n    Statement st = null;\r\n    ResultSet rs = null;\r\n\r\n    String url = \"jdbc:mysql:\/\/example.com:3306\/finance\";\r\n    String user = \"john_doe\";\r\n    String password = \"P@ssw0rd\";\r\n\r\n    try {\r\n      con = DriverManager.getConnection(url, user, password);\r\n      st = con.createStatement();\r\n      rs = st.executeQuery(\"select * from accounts\");\r\n\r\n      ResultSetMapper&lt;Account&gt; resultSetMapper = new ResultSetMapper&lt;Account&gt;();\r\n      List&lt;Account&gt; accountList = resultSetMapper.mapRersultSetToObject(rs, Account.class);\r\n\r\n      \/\/ print out the list retrieved from database\r\n      if(accountList != null){\r\n        for(Account account : accountList){\r\n          System.out.println(account);\r\n        }\r\n      } else {\r\n        System.out.println(\"ResultSet is empty. Please check if database table is empty\");\r\n      }\r\n\r\n      con.close();\r\n    } catch (SQLException e) {\r\n      e.printStackTrace();\r\n    }\r\n  }\r\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Did you ever wanted \u00a0to implement simple mapping of database tables to java objects (models) and you wanted to do the whole stuff dynamically? I managed to put some code together which does exactly what you wanted<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"Java - Map ResultSet to Object dynamically","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[249,9,10],"tags":[254,70,256,255,257,253,250,252,258],"class_list":["post-900","post","type-post","status-publish","format-standard","hentry","category-database-development","category-development","category-java","tag-annotation","tag-database","tag-getannotation","tag-getdeclaredfields","tag-isannotationpresent","tag-reflection","tag-resultset","tag-resultsetmetadata","tag-setproperty"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p3nYbe-ew","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/oprsteny.cz\/index.php?rest_route=\/wp\/v2\/posts\/900","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/oprsteny.cz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/oprsteny.cz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/oprsteny.cz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/oprsteny.cz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=900"}],"version-history":[{"count":1,"href":"https:\/\/oprsteny.cz\/index.php?rest_route=\/wp\/v2\/posts\/900\/revisions"}],"predecessor-version":[{"id":901,"href":"https:\/\/oprsteny.cz\/index.php?rest_route=\/wp\/v2\/posts\/900\/revisions\/901"}],"wp:attachment":[{"href":"https:\/\/oprsteny.cz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=900"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/oprsteny.cz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=900"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/oprsteny.cz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=900"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}