I've recently started working on a new project in Java which will have a local database. As part of the design, I have created an AbstractEntity class - this is intended as an object representation of a row (or potential row) on the database.
I've run into a few issues early on in this design though and want to make sure I'm not going down a bad path. One particular method I'm having trouble with is the following:
public ArrayList retrieveEntities(String sql)
{
ArrayList ret = new ArrayList();
String query = "SELECT " + getColumnsForSelectStatement() + " FROM " + getTableName() + " WHERE " + sql;
try (Connection conn = DatabaseUtil.createDatabaseConnection();
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery(query))
{
while (rs.next())
{
AbstractEntity entity = factoryFromResultSet(rs);
ret.add(entity);
}
}
catch (SQLException sqle)
{
Debug.logSqlException(query, sqle);
}
return ret;
}
The idea behind this method is to have a generic way to retrieve things from the database, where the only thing I have to pass in are the conditions for the SQL. As it stands it works correctly, but I have two problems with it:
1) Type Safety
I can't seem to parameterise this method without causing compiler errors. ArrayList<AbstractEntity>
is no good, and I can't seem to get ArrayList<? extends AbstractEntity>
to work either. When I try the latter (which makes sense to me), the following line gives me a compiler error:
ArrayList<PlayerEntity> list = new PlayerEntity().retrieveEntities("1 = 1");
The error is 'Type mismatch: cannot convert from ArrayList<capture#1-of ? extends AbstractEntity>
to ArrayList<PlayerEntity>
'
Is there a way I can directly reference the superclass from an abstract class? This method isn't static, and since you cannot instantiate an abstract class (it has no constructor), to call this I must always have an extending class. So why can't I reference it's type?
2) Staticness
Ideally, I'd like for this method to be static. That way I can call PlayerEntity.retrieveEntities() directly, rather than making an object just to call it. However, since it refers to abstract methods I can't do this, so I'm stuck with it.
Both of the above gripes are ringing alarm bells in my head. Is there a better way to design this that avoids these problems, or better yet are there direct solutions to either of these problems that I'm missing?