我一直苦苦挣扎了很长一段时间,并且已经查看了一些资源,试图理解我如何使用泛型来获得我想要实现的目标,但却未能找到一个提供我的例子需要。
一些例子包括使用Supplier接口或建议使用泛型类然后实例化它。
我想要实现的是指定我希望方法返回的类型,同时在方法中实例化相同类型并将其添加到列表中,然后返回该列表。
提前致谢。非常感谢任何帮助
public List<Doctor> queryDoctor() {
Statement statement = null;
ResultSet results;
try {
statement = connection.createStatement();
results = statement.executeQuery("SELECT * FROM " + TABLE_DOCTOR);
List<Doctor> doctors = new ArrayList<>();
while (results.next()) {
Doctor doctor = new Doctor();
doctor.setId(results.getInt(1));
doctor.setUserName(results.getString(2));
doctor.setPassword(results.getString(3));
doctor.setPassword_salt(results.getString(4));
doctor.setRole(results.getInt(5));
doctors.add(doctor);
}
return doctors;
} catch (SQLException e) {
System.out.println("Query failed: " + e.getMessage());
return null;
} finally {
try {
if (statement != null) {
statement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:2)
您需要传递Function<ResultSet, T>
:
<T> List<T> queryDoctor(Function<ResultSet, T> fn)
并在循环中使用它:
doctors.add(fn.apply(results));
此函数将创建适当的具体类型:
List<Doctor> doctors = queryDoctor(results -> {
Doctor doctor = new Doctor();
doctor.setId(results.getInt(1));
doctor.setUserName(results.getString(2));
doctor.setPassword(results.getString(3));
doctor.setPassword_salt(results.getString(4));
doctor.setRole(results.getInt(5));
return doctor;
});
或
List<Nurse> nurses = queryDoctor(results -> {
Nurse nurse = new Nurse();
// ...
return nurse;
});
答案 1 :(得分:0)
听起来您正在尝试自己的简单ORM解决方案,其中提供带有SQL字符串和类型的方法,该方法加载结果然后实例化类型,将结果集映射到对象的字段通过塞特犬。
如果是这样,你就重新发明了轮子。
完整的解决方案是使用像Hibernate或Top Link这样的ORM工具,但可以在你走路之前运行。如果您更喜欢婴儿步骤,请考虑使用Spring的Jdbc模板来处理许多样板代码。
更新
好的,我问你是否正在寻找一个采用结果集并将其映射到任意类的方法,你说是的。这应该是这样的:
public <T> List<T> map(ResultSet rs, Class<T> clazz) throws Exception {
//// Build a list of columns that are in the resultset
List<String> columns = new LinkedList<>();
ResultSetMetaData metaData = rs.getMetaData();
for(int i=0; i < metaData.getColumnCount(); i++) {
columns.add(metaData.getCatalogName(i));
}
//// Create a list to hold all the beans we are going to create from the resultset
List<T> rows = new LinkedList<>();
//// Iterate over each row in the resultset, creating beans for each row and setting the values
while(rs.next()) {
//// Create a new instance of the class passed in (must have a no-args constructor)
T row = clazz.newInstance();
//// Now for the magic. This bit is very noddy and ORM packages will do this much better
for(String col : columns) {
//// For each column that is in the resultset, find the setter in the bean class
String columnValue = rs.getString(col);
String mutator = "set"+capitalizeFirstCharacter(col);
Method m = clazz.getMethod(mutator, String.class);
//// Invoke the setter, passing in the value from the resultset
m.invoke(row, columnValue);
}
rows.add(row);
}
return rows;
}
private static String capitalizeFirstCharacter(String s) {
return s.substring(0, 1).toUpperCase() + s.substring(1);
}
请注意,此代码不处理异常,仅适用于填充了Strings的结果集,并且只处理具有要填充的String字段的bean。一旦你开始尝试编写更复杂的代码来处理更复杂的类型和反射......你正在重新发明ORM。尽量不这样做。