如何以自定义方式处理多行结果?
How to process multi-row result in a custom way?
目前我的方法体如下所示:
jdbcTemplate.query(queryJoiningTwoTables, (rs, rowNum) -> {
final long id= rs.getLong("id");
MyObject obj = jobStatusBunchMap.get(id);
if (obj== null) {
OffsetDateTime offsetDateTime = rs.getObject("creation_timestamp", OffsetDateTime.class);
...
obj = new MyObject (offsetDateTime ...);
map.put(id, obj );
}
String jobId = rs.getString("job_id");
obj.getJobIds().add(jobId);
return null;
});
return map.values();
看来我使用 API 的方式不正确。
有没有更好的方法来达到同样的效果?
P.S.
我尝试使用 jdbcTemplate#queryForRowSet
但在这种情况下 rs.getObject("creation_timestamp", OffsetDateTime.class)
抛出异常,表明它不受支持的操作。
有很多选项可以使用 jdbcTemplate 映射结果,包括您的选项。
也许这会帮助您更好地理解它:
public List<Action> findAllActions() {
final String selectStatement = "SELECT id,name FROM Actions"; // or your query
try {
return jdbcTemplate.query(selectStatement,(resultSet, rowNum) -> {
int actionId = resultSet.getInt("id");
String actionName = resultSet.getString("name");
Action action = new Action();
action.setId(actionId);
action.setName(actionName);
return action;
});
} catch (EmptyResultDataAccessException e) {
LOGGER.error("Get all actions - empty set", e);
return Collections.emptyList();
}
}
如果没有 lambda 表达式,您可以像这样使用 jdbcTemplate 查询:
public List<Action> findAllActions() {
final String selectStatement = "SELECT id,name FROM Actions"; // or your query
try {
return jdbcTemplate.query(selectStatement, getActionRowMapper());
} catch (EmptyResultDataAccessException e) {
LOGGER.error("Get all actions - empty set", e);
return Collections.emptyList();
}
}
private RowMapper<Action> getActionRowMapper() {
return (resultSet, rowNum) -> {
int actionId = resultSet.getInt("id");
String actionName = resultSet.getString("name");
return action;
};
}
如您所见,jdbcTemplate.query 方法的第二个参数采用 RowMapper<Action>
类型,但使用 lambda 表达式隐藏。这个选项是 "restricting" 除了为每一行映射结果集和 return 结果之外,你可以做任何其他事情。最终结果最终将是 List
个动作。
第二个选项是使用 ResultSetExtractor
,它可以让您遍历结果集并提供更大的灵活性。查询将是相同的,只是 jdbcTemplate.query 方法的第二个参数将被更改。为此,我会亲自实现 ResultSetExtractor
并覆盖 extractData 方法,或者如果您不需要其他任何东西来映射结果
public List<Group> findGroups() {
final String selectStatement = "SELECT stud.id, stud.name, gr.id, gr.name FROM student stud INNER JOIN group gr ON gr.id=stud.group_id ORDER BY stud.id"; // or your query
try {
return jdbcTemplate.query(selectStatement, new GroupExtractor() );
} catch (EmptyResultDataAccessException e) {
LOGGER.error("Get all groups - empty set", e);
return Collections.emptyList();
}
}
public class GroupExtractor implements ResultSetExtractor<List<Group>> {
@Override
public List<Group> extractData(ResultSet resultSet) {
Map<Group, List<Student>> studentsGroup= new HashMap<>();
List<Group> groups = new ArrayList<>();
try {
while (resultSet.next()) {
int studentId = resultSet.getInt("stud.id");
String studentName = resultSet.getString("stud.name");
int groupId = resultSet.getInt("gr.id");
String groupName = resultSet.getString("gr.name");
Group group = createGroup(groupId, groupName);
Student student = createStudent(studentId, studentName);
studentsGroup.putIfAbsent(group, new ArrayList<>());
studentsGroup.get(group).add(student);
}
studentsGroup.forEach((group,students) ->{
group.setStudents(students);
groups.add(group);
}
return groups;
} catch (SQLException e) {
LOGGER.info("An error occured during extracting data", e);
}
return actions;
}
private Student createStudent(String studentId, String studentName)
{
Student student=new Student();
student.setId(studentId);
student.setName(studentName);
return student;
}
//idem for createGroup
}
目前我的方法体如下所示:
jdbcTemplate.query(queryJoiningTwoTables, (rs, rowNum) -> {
final long id= rs.getLong("id");
MyObject obj = jobStatusBunchMap.get(id);
if (obj== null) {
OffsetDateTime offsetDateTime = rs.getObject("creation_timestamp", OffsetDateTime.class);
...
obj = new MyObject (offsetDateTime ...);
map.put(id, obj );
}
String jobId = rs.getString("job_id");
obj.getJobIds().add(jobId);
return null;
});
return map.values();
看来我使用 API 的方式不正确。
有没有更好的方法来达到同样的效果?
P.S.
我尝试使用 jdbcTemplate#queryForRowSet
但在这种情况下 rs.getObject("creation_timestamp", OffsetDateTime.class)
抛出异常,表明它不受支持的操作。
有很多选项可以使用 jdbcTemplate 映射结果,包括您的选项。 也许这会帮助您更好地理解它:
public List<Action> findAllActions() {
final String selectStatement = "SELECT id,name FROM Actions"; // or your query
try {
return jdbcTemplate.query(selectStatement,(resultSet, rowNum) -> {
int actionId = resultSet.getInt("id");
String actionName = resultSet.getString("name");
Action action = new Action();
action.setId(actionId);
action.setName(actionName);
return action;
});
} catch (EmptyResultDataAccessException e) {
LOGGER.error("Get all actions - empty set", e);
return Collections.emptyList();
}
}
如果没有 lambda 表达式,您可以像这样使用 jdbcTemplate 查询:
public List<Action> findAllActions() {
final String selectStatement = "SELECT id,name FROM Actions"; // or your query
try {
return jdbcTemplate.query(selectStatement, getActionRowMapper());
} catch (EmptyResultDataAccessException e) {
LOGGER.error("Get all actions - empty set", e);
return Collections.emptyList();
}
}
private RowMapper<Action> getActionRowMapper() {
return (resultSet, rowNum) -> {
int actionId = resultSet.getInt("id");
String actionName = resultSet.getString("name");
return action;
};
}
如您所见,jdbcTemplate.query 方法的第二个参数采用 RowMapper<Action>
类型,但使用 lambda 表达式隐藏。这个选项是 "restricting" 除了为每一行映射结果集和 return 结果之外,你可以做任何其他事情。最终结果最终将是 List
个动作。
第二个选项是使用 ResultSetExtractor
,它可以让您遍历结果集并提供更大的灵活性。查询将是相同的,只是 jdbcTemplate.query 方法的第二个参数将被更改。为此,我会亲自实现 ResultSetExtractor
并覆盖 extractData 方法,或者如果您不需要其他任何东西来映射结果
public List<Group> findGroups() {
final String selectStatement = "SELECT stud.id, stud.name, gr.id, gr.name FROM student stud INNER JOIN group gr ON gr.id=stud.group_id ORDER BY stud.id"; // or your query
try {
return jdbcTemplate.query(selectStatement, new GroupExtractor() );
} catch (EmptyResultDataAccessException e) {
LOGGER.error("Get all groups - empty set", e);
return Collections.emptyList();
}
}
public class GroupExtractor implements ResultSetExtractor<List<Group>> {
@Override
public List<Group> extractData(ResultSet resultSet) {
Map<Group, List<Student>> studentsGroup= new HashMap<>();
List<Group> groups = new ArrayList<>();
try {
while (resultSet.next()) {
int studentId = resultSet.getInt("stud.id");
String studentName = resultSet.getString("stud.name");
int groupId = resultSet.getInt("gr.id");
String groupName = resultSet.getString("gr.name");
Group group = createGroup(groupId, groupName);
Student student = createStudent(studentId, studentName);
studentsGroup.putIfAbsent(group, new ArrayList<>());
studentsGroup.get(group).add(student);
}
studentsGroup.forEach((group,students) ->{
group.setStudents(students);
groups.add(group);
}
return groups;
} catch (SQLException e) {
LOGGER.info("An error occured during extracting data", e);
}
return actions;
}
private Student createStudent(String studentId, String studentName)
{
Student student=new Student();
student.setId(studentId);
student.setName(studentName);
return student;
}
//idem for createGroup
}