refactoring - Java Data-Entity model: Constructing general types -


i have had trouble using general type in static method.

all comments on source code welcome, ones improve code. not planning on using external framework, apart jdbc, keep still simple, please not put emphasis on that.

my view on not using external frameworks supported fact operations using on database minimal:

  • inserting data
  • updating data
  • retrieving all fields. (and putting in different sql query select fields retrieve

i not plan on making full framework, know not supporting everything. speed of retrieving fields neither real issue, pretty done on server bootup, , if used @ other time done in background task not care when finished.

entity.java:

abstract public class entity<keytype, datatype> {     protected keytype key;     protected list<object> data;      public entity() {         data = new arraylist<>();     }      //abstract public static map<keytype, datatype> getall();      protected list<object> createdata(final dataaction dataaction) {         list<object> list = new arraylist<>();         if (dataaction == dataaction.insert) {             list.add(key);         }          list.addall(data);          if (dataaction == dataaction.update) {             list.add(key);         }         return list;     }      abstract public void insert();      abstract public void update();      protected static <keytype, datatype> map<keytype, datatype> getdata(final class<datatype> datatypeclass, final string query) {         map<keytype, datatype> map = new hashmap<>();         try {             preparedstatement preparedstatement = databaseconnection.getconnection().preparestatement(query);             resultset resultset = preparedstatement.executequery();             while (resultset.next()) {                 keytype key = (keytype)resultset.getobject(1);                 int index = 2;                 list<object> datalist = new arraylist<>();                 while (resultset.getobject(index) != null) {                     datalist.add(resultset.getobject(index));                     index++;                 }                 datatype dataobject = null;                 try {                     dataobject = datatypeclass.getconstructor(list.class).newinstance(datalist);                 } catch (instantiationexception | illegalaccessexception | illegalargumentexception | invocationtargetexception | nosuchmethodexception | securityexception ex) {                     logger.getlogger(entity.class.getname()).log(level.severe, null, ex);                 }                 map.put(key, dataobject);             }         } catch (sqlexception ex) {             logger.getlogger(entity.class.getname()).log(level.severe, null, ex);         }                 return map;     }      protected void executequery(final string query, final list<object> data) {         try {             preparedstatement preparedstatement = databaseconnection.getconnection().preparestatement(query);             int dataindex = 0;             (object dataobject : data) {                 preparedstatement.setobject(dataindex, dataobject);                 dataindex++;             }             preparedstatement.execute();             preparedstatement.close();         } catch (sqlexception ex) {             logger.getlogger(entity.class.getname()).log(level.severe, null, ex);         }     } } 

a concrete implementation, account.java:

public class account extends entity<string, account> {     private final static string select_all_query = "select * accounts";     private final static string insert_query = "insert accounts (username, password) values(?, ?)";     private final static string update_query = "update accounts set password=? username=?";      private string username;     private string password;      public account(final string username, final string password) {         this.username = username;         this.password = password;          key = username;         data.add(password);     }      public account(final list<object> data) {         this((string)data.get(0), (string)data.get(1));     }      public string getusername() {         return username;     }      public void setusername(final string username) {         this.username = username;     }      public string getpassword() {         return password;     }      public void setpassword(final string password) {         this.password = password;     }      public static map<string, account> selectall() {         return getdata(account.class, select_all_query);     }      @override     public void insert() {         executequery(insert_query, createdata(dataaction.insert));     }      @override     public void update() {         executequery(update_query, createdata(dataaction.update));     } } 

i happy concrete implementation, seems have managed bring down bare minimum, except public account(final list<object> data) not seem nice, can live it.

however, guessed, getdata() entity definately not nice, , improve if possible.

what use datatype dataobject = new datatype(datalist), seems generic type arguments cannot instantiated.

so there ways of optimizing current code in current view? , possible decouple concrete classes , abstract classes more?

edit:

added relevant question (i don't think should make new question thing, right?):

is there way move static strings (sql queries) , insert() , update() out of account class, entity class?

to avoid use of reflection in getdata method should accept factory given resultset creates instances of specific type. selectall method like:

public static map<string, account> selectall()  {   return getdata(     new entityfactory<account>()     {       public account newinstance(resultset resultset) throws sqlexception       {         return new account(resultset.getstring(0), resultset.getstring(1));       }     },     select_all_query   ); } 

the getdata method ends like:

protected static <k, t extends entity<k>> map<k, t> getdata(entityfactory<t> entityfactory, string query)  {   connection connection = null;   preparedstatement preparedstatement = null;         resultset resultset = null;    try    {     connection = datasource.getconnection();      preparedstatement = connection.preparestatement(query);      resultset = preparedstatement.executequery();      map<k, t> entities = new hashmap<>();      while (resultset.next())      {       entity<k> entity = entityfactory.newinstance(resultset);       entities.put(entity.getkey(), entity);     }      return entities;   }      {     closequietly(resultset);     closequietly(preparestatement);     closequietly(connection);   } } 

and assumes entity looks like:

public interface entity<k> {   public k getkey(); } 

this allows remove reflection , keeps code understands database structure in 1 place. should use similar template pattern map domain object prepared statement when doing inserts , updates.

now you've asked comments on code in general.

first off, code violates single responsibility principal , seperation of concerns. domain class should domain class , not contain persistance logic. @ patterns data access object how should done.

second, while i'm keeping simple, hibernate solved problem long time ago , jpa standardized - need reason not use 1 or both of these apis.

finally, use of database resources - if going use jdbc directly have clean properly. database connections expensive resources , should handled such, basic template jdbc call should be:

connection connection = null; preparedstatement preparedstatement = null; resultset resultset = null;  try  {   connection = //get connection pool or single instance.    preparedstatement = connection.preparestatement("select * table column = ?");   preparedstatement.setstring(1, "some string");    resultset = preparedstatement.executequery();    while (resultset.next())   {     //logic goes here.   } } catch (sqlexception e) {   //handle exceptions. }  {   closequietly(resultset);   closequietly(preparestatement);   closequietly(connection); } 

the closequietly method has overloaded should take general form:

try  {   if (resultset != null)   {     resultset.close();   } } catch (sqlexception e) {     //log exceptions don't re-throw. }  

Comments

Popular posts from this blog

jquery - How can I dynamically add a browser tab? -

node.js - Getting the socket id,user id pair of a logged in user(s) -

keyboard - C++ GetAsyncKeyState alternative -