我目前有以下代码从数据库中检索数据,然后创建User
。在我的许多classe中使用此代码来创建其他对象,例如News
,Comments
等...
它使用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);
是否可以将QueryRunner
包装在泛型类中并覆盖查询方法,以便处理程序使用ResultSet实现通用T
。我会确保任何T
类型都是接受ResultSet
的构造函数。
像这样:
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;
}
};
}
}
我不知道你是否理解,但我希望如此,请问我是否需要更多细节或更好的解释。
修改
我以为我可以使用AbstractClass而不是所有不同对象都会扩展的泛型类型,但似乎我无法编写抽象构造函数。我是否必须创建一个返回对象实例的静态方法,如:
public abstract class DatabaseEntity {
public static abstract DatabaseEntity create(ResultSet rs);//even this doesn't work...
}
答案 0 :(得分:8)
可能,是吗?但这是一个坏主意。
你可以这样做:
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;
}
}
然而,混合域和数据库是一个坏主意。然而,更好的方法是定义一个基于结果集创建对象的abtract方法:
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;
}
}
然后,在您的实现类中,您只需要提供create()
方法而不是自己处理结果集,例如:
h = new ResultSetHandler<Person>() {
protected Person create(ResultSet rs) {
return new Person(rs.getString("name"));
}
}
答案 1 :(得分:3)
你可以做类似的事情(通过传递对象的类来创建,并使用反射来调用它的构造函数),但是我觉得让POJO依赖于JDBC并且不仅仅知道它是如何设计的糟糕设计存储在数据库中,但也在用于加载它的查询中使用了哪些别名。
简而言之,用户POJO构造函数不负责处理外部未知查询的结果集。
你可以设计一个只有
的AbstractSingleEntityHandler超类if (rs.next()) {
阻止,并将实际的实体创建委托给抽象方法,但你不会获得太多收益。
答案 2 :(得分:0)
我认为在Java中不可能这样做。您无法在通用中创建T
的实例。 java中的泛型不是C ++中的模板,它们只是object
周围的语法糖,它会删除强制转换并引发编译时警告。
在C#中没有办法约束T
,因此必须有一个构造函数。
如果真的有必要,最好的办法是使用反射来解析相应的类,但即使这样你也会遇到问题,因为在调用方法时你无法知道T的运行时类 - 这个信息是从java字节码。因此,您可以将类传递给方法,以便对其进行反射。而且我不太确定这是一个好的设计理念。