Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java generic constructors

I currently have the following code that retrieves data from the database and then create a User. This code is used in many of my classe to create other objects such as News, Commentsetc...

It uses apache commons dbutils.

final ResultSetHandler<User> handler = new ResultSetHandler<User>() {

            @Override
            public User handle(ResultSet rs) throws SQLException {

                User user = null;
                if (rs.next()) {
                    user = new User();
                    user.setId(rs.getInt("id"));
                    user.setUsername(rs.getString("username"));
                    user.setPassword(rs.getString("password"));
                }
                return user;
            }
        };

        final User user = run.query(
                "SELECT id, username, password FROM users WHERE username = ? AND active = 2 LIMIT 1;", handler,
                username);

Would it be possible to wrap the QueryRunner in a generic class and override the query method so the handler instanciate the generic T with the ResultSet. I would make sure any Ttype would ahve a constructor accepting a ResultSet.

Like so :

        public class QueryExecuter<T> extends QueryRunner {
    private ResultSetHandler<T> _handler;

    public QueryExecuter(){//The T type was for testing haha
        super();
        handler = new ResultSetHandler<T>() {

            @Override
            public T handle(ResultSet rs) throws SQLException {

                T object = null;
                if (rs.next()) {
                    object = new T(rs);
                }
                return object;
            }
        };
    }
}

I don't know if you'll understand, but I hope so, ask me if you want more details or a better explanation.

EDIT

I thought I could use a AbstractClass instead of the generic type that all of the differents objects would extends but it seems like I can't write an abstract constructor. Will I have to make a static method that return an instance of the object like:

public abstract class DatabaseEntity {
    public static abstract DatabaseEntity create(ResultSet rs);//even this doesn't work...
}
like image 630
David Avatar asked Feb 07 '12 20:02

David


People also ask

What is generic constructor in Java?

A generic constructor is a constructor that has at least one parameter of a generic type. We'll see that generic constructors don't have to be in a generic class, and not all constructors in a generic class have to be generic.

Do generic classes have constructors?

No, generic constructors are not allowed.

How do you construct a generic constructor?

Generic constructors are the same as generic methods. For generic constructors after the public keyword and before the class name the type parameter must be placed. Constructors can be invoked with any type of a parameter after defining a generic constructor.

Is it possible to make a constructor generic explain with code?

Constructors As Generics : As we all know that constructors are like methods but without return types. Like methods, constructors also can be generic. Even non-generic class can have generic constructors. Here is an example in which constructor of a non-generic class is defined as generic.


2 Answers

Possible, yes? But its a bad idea.

You could do:

class ResultSetHandler<T> {
  ResultSetHandler<T>(Class<T> clazz) {
    this.clazz = clazz;
  }

  public T handle(ResultSet rs) throws SQLException {
    T object = null;
    if (rs.next()) {
      object = clazz.getConstructor(ResultSet.class).newInstance(rs)
    }
    return object;
  }
}

Mixing domain and database is a bad idea, however. What would be better, however, would be to define an abtract method that creates the object based on the resultset:

abstract class ResultSetHandler<T> {

  protected abstract T create(ResultSet rs);

  public T handle(ResultSet rs) throws SQLException {
    T object = null;
    if (rs.next()) {
      object = create(rs);
    }
    return object;
  }
}

Then, in your implementing class, you only need to provide a create() method instead of handling the result set yourself, for example:

h = new ResultSetHandler<Person>() {
  protected Person create(ResultSet rs) {
    return new Person(rs.getString("name"));
  }
}
like image 196
Reverend Gonzo Avatar answered Oct 06 '22 16:10

Reverend Gonzo


You could do something like that (by passing the class of the object to create, and use reflection to call its constructor), but I would find it bad design to have the POJO dependent on JDBC, and knowing not only how it's stored in database, but also which aliases have been used in the query used to load it.

In short, it's not the responsibility of the User POJO constructor to handle a result set of an external, unknown query.

You could design an AbstractSingleEntityHandler superclass which would just have the

if (rs.next()) {

block, and would delegate the actual entity creation to an abstract method, but you wouldn't gain much.

like image 22
JB Nizet Avatar answered Oct 06 '22 14:10

JB Nizet