samedi 14 novembre 2015

Using reflection API for database class

I have the following abstract base class that is used to map its subclass objects into a relational database. insertIntoDatabase() method would invoke the toTuple() method from its subclass. It then uses the tuple returned by the subclass to form a SQL Insert statement.

For example) if toTuple returns ["johns","john","smith","443-235-6642"] databaseQueryBuilder.insertStatement("User',tuple) method would form the SQL statement such as "INSERT INTO User VALUES('johns','john','smith','443-235-6642');

package model;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;

public abstract class Model {
    protected DatabaseQueryBuilder databaseQueryBuilder;
    protected String primaryKey;
    protected int columnCount;
    protected Class aClass;

    public Model(String primaryKey) {
        this.primaryKey = primaryKey;
        this.databaseQueryBuilder = new DatabaseQueryBuilder(Database.getInstance());
        this.aClass = getClass();
    }

    public ArrayList selectFromDatabase(String[] columns, HashMap pairs) {
        return databaseQueryBuilder.selectStatementWithWhereClause(
                aClass.getSimpleName(), columns, pairs);
    }
    /*
    template pattern implement
    toTuple template method
     */
    public StatusCode insertIntoDatabase() {
        Object[] tuple = toTuple();
        return databaseQueryBuilder.insertStatement(
                aClass.getSimpleName(), tuple);
    }
    //write the object's data into a tuple
    //getter
    public abstract Object[] toTuple();
    //set the object's field
    //setter
    public abstract void updateField(String fieldName, String value);
}

The problem with this design is that all the sub-classes of Model have to override the toTuple methods. But toTuple methods in all the sub-classes would be the same:

package model;

import java.lang.reflect.Field;

public class Product extends Model {

    public Product() {
        super("productid");
    }

    public Object[] toTuple()  {
        Object[] tuple = new Object[columnCount];
        Field[] fields = aClass.getDeclaredFields();
        int index = 0;
        for (Field field : fields) {
            if (index < columnCount) {
                try {
                    tuple[index] = field.get(this);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            index++;
        }
        return tuple;
    }

    private String productid = "AUTO INCREMENT";
    private String productName;
    private double sellingPrice;
    private double cost;
    private int quantity;
    private String imagePath;
    private String category;
    private String owner;
    private String description;
}

I cannot implement toTuple() in the super class because the sub class properties are private.

Is there anyway I can improve my design? Thank you so much for your feedback





Aucun commentaire:

Enregistrer un commentaire