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
, Comments
etc...
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 T
type 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...
}
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.
No, generic constructors are not allowed.
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.
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.
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"));
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With