2

I think this explains my question well enough:

public class Model {
    public static Model [] findAllBySQL(String SQL){
        //this is simplified.  It should really query the DB and then fill model(s) with the DB values, and return the model(s).  sql query can return more than one row
        return new this(); //sytax error here
    }
}


public class UserModel extends Model {

}


UserModel.findAllBySQL("firstname=john") //How do I design the above so this returns a UserModel object?

I'm relatively new to Java. My background is mostly PHP. I am trying to create a simple home-made active record system.. I know this is recreating the wheel, but that's how I learn :)

EDIT: Most of you guys misunderstood me. I know how to simple to new UserModel(). I changed the code to make it more clear.

7
  • @Jonah - see edited answer, is that what you meant? Commented Apr 10, 2011 at 5:41
  • Are you expecting this to query an SQL database and return an object filled in with values from that database? If so look into a library called "Hibernate". Java does not have any SQL integration built-in. Commented Apr 10, 2011 at 6:04
  • @Bill I heard about Hibernate but I would rather create my own library, in order to learn Java better and since I need something ultra simple right now. Also, I am using java.sql Commented Apr 10, 2011 at 6:09
  • In that case you need to use an SQL class library (like download.oracle.com/javase/1.4.2/docs/api/java/sql/…) to execute a query, then create a class with exactly the same attributes (variables) as you have in the table. You then copy over each variable by hand from the query into the class. This is exactly why they created hibernate, it's what hibernate does. Commented Apr 10, 2011 at 6:19
  • I was thinking of storing the results of the query into a HashMap in the model. Then there would be a getAttribute(String attribute) method in the Model class, which returns the attribute. I can't argue that this is a better approach than Hibernate's.. but it doesn't require you to list all the table attributes as class attributes Commented Apr 10, 2011 at 6:39

6 Answers 6

2

You should use a constructor:

public class Model {
    //Constructor
    public Model()
    {
    // Do initialization stuff here
    }
}


public class UserModel extends Model {
    //Constructor
    public UserModel()
    {
    // Do initialization stuff here
    }
}

To create new object, you call it like that:

UserModel myUserModel;    // Declare new object reference
myUserModel = new UserModel();   // create new object of this class

Edit:

If you declare the method as a method returning array of Models, you can't return a single model, you may return a Model array with one Model, but not a single object.

For example

public static Model [] findAllBySQL(String SQL){
    // find how many models do you have
    Model[] models = new Model[numberOfModels];
    for (Model model : models)
    {
         model = new Model();
         //do what you want with it...
    }
    return models; //sytax error here
}
Sign up to request clarification or add additional context in comments.

2 Comments

This will not do because I can not be redefining findBySQL() in every Model sub-class.. Trying to be DRY here..
@Jonah - is that what you're looking for?
2

Why not simply use new operator as

UserModel userModel = new UserModel();

To know different ways to create an object in java see this thread: what-are-all-the-different-ways-to-create-an-object-in-java


Edit

Based on your edit what you can do is?

public static Model findBySQL(String SQL){
        Model model = new Model();
        // Now query in db to get data. then use setter methods of Model to set data in object
        // i.e. model.setXXX(XXX);
        // and finally return that model object.
        return model;
    }

Edit 2

UserModel could have getFullName() which concatenates the first name with the last name from the db. I would need to be able to access this method straight away on the object returned from findBySQL

You can try like this: in UserModel,

public String getFullName(){
    Model model = findBySql("str='str'");
    return model.getFirstName()+"  "+model.getLastName();
}

5 Comments

I don't think so.. this will return a Model object.. but I need an object of the type of the caller..
@Jonah: Because UserModel extends Model you can easily parse it to caller. Or You can change the return type to caller.
Not sure what you mean (I am new to Java, remember). I would need to be able to call methods from the sub-class. Eg UserModel could have getFullName() which concatenates the first name with the last name from the db. I would need to be able to access this method straight away on the object returned from findBySQL
No.. I need it to be more flexible. For instance I want usage like this: UserModel u = UserModel.findBySQL(...); print(u.getFullName()); print(u.getOtherDynamicField());
@Jonah: then you should try using generic types.
1

Sounds like you need the Factory Method Pattern. If you have a Model super class and several types of Models then you can encapsulate the object creation in a ModelFactory class with a createModel() method that returns the appropriate type of Model based on the parameter to the method.

 class ModelFactory(){
       public Model createModel(String sql, String type){
            //execute SQL

            if(type.equals("user")){
                 UserModel model = new UserModel();
                 //set the attributes here
                 return model;
            }

            if(type.equals("other")){
                 OtherModel model = new OtherModel();
                 //set attributes here
                 return model;
            }

             //etc
       }
 }

To actually get a Model object you can now:

       ModelFactory factory = new ModelFactory();
       Model m = factory.createModel("select * from mytable", "user");

2 Comments

This is the best solution so far. The only thing I don't like: createModel() is not DRY. Any way to make it DRY? I do not want to have to add to createModel() every time I add a new model to my application :/ (Rant: This is why I do not like strong typing)
The advantage of the Factory pattern is that the object creation logic is encapsulated in one place, unfortunately that place needs to be changed as your model changes. It may be possible to use reflection to avoid this. See download.oracle.com/javase/tutorial/reflect/member/… for some details on instantiating objects by reflection.
0

This is how you use this

UserModel m = new UserModel();

UserModel m now has all functions/values from
UserModel + the functions/values from Model.

Example

public class Model {
    public Model()
    {
    // Do initialization stuff here
    }

    public getVal(){
        return 1+1;
    }
}


public class UserModel extends Model {
    public UserModel()
    {
    // Do initialization stuff here
    }

    public getValue2(){
        return 2+2;
    }
}


UserModel m = new UserModel();

m.getVal(); //Will return 2
m.getValue2(); // Will return 4

Comments

0

You can do it in this way :

import java.util.ArrayList;
import java.util.List;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;

public class Generics<T> {

    //method that returns a generic list
    public List<T> findAllBySQL(String SQL) {
        throw new NotImplementedException();
    }

    public static void main(String[] args) {
        //base class that returns a list of childs
        Generics result = new ExtendedGenerics(null);
        List<ExtendedGenerics> genericArray = result.findAllBySQL(null);
        for (ExtendedGenerics item : genericArray) {
            System.out.println(item);
        }
    }
}

//extend base class and specify generic type
class ExtendedGenerics extends Generics<ExtendedGenerics> {

    private String myMessage;

    public ExtendedGenerics(String yourMessage) {
        myMessage = yourMessage;
    }

    @Override
    //overriding base method, so it return a instances list of this class 
    public List<ExtendedGenerics> findAllBySQL(String SQL) {
        ArrayList<ExtendedGenerics> result = new ArrayList<ExtendedGenerics>();
        result.add(new ExtendedGenerics("I am first"));
        result.add(new ExtendedGenerics("I am second"));
        result.add(new ExtendedGenerics("I am third"));
        return result;
    }

    @Override
    public String toString() {
        return "ExtendedGenerics{" + myMessage + '}';
    }
}

So in this way no casting in necessary. This is the output of the code :

ExtendedGenerics{I am first}
ExtendedGenerics{I am second}
ExtendedGenerics{I am third}

Comments

0

You can use Factory Method plus Java Generics:

public class Model {
  public static <T> T[] findAllBySQL(String SQL, Class<T extends Model> type) {
    T[] result = new T[123];
    for (int i = 0; i < 123; i++) {
      result[i] = type.newInstance();
    }
    return result;
  }
}
public class UserModel extends Model {
}
Model[] rowset = UserModel.findAllBySQL("firstname=john", UserModel.class); 

I assume this is the alternative of a plain simple PHP construct:

new $type();

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.