Spring Boot中传递JdbcTemplate.queryForList结果及数据源异常解决
首先得明确:你遇到的Property 'dataSource' is required错误,根本不是返回结果的问题,而是Spring的依赖注入机制没生效导致的。咱们一步步拆解问题和解决方案:
问题根源分析
你在EmployeeServiceImpl里手动执行了new EmployeeDAO(),这个通过new创建的EmployeeDAO实例不在Spring容器的管理范围内。也就是说,你在EmployeeDAO里用@Autowired标注的dataSource完全没有被Spring注入,它的值是null。当你用这个null的dataSource去初始化JdbcTemplate时,自然就抛出了数据源必填的异常。
正确的解决方案
1. 让EmployeeDAO成为Spring管理的Bean
在EmployeeDAO类上添加@Repository注解(DAO层专用的Bean注解,Spring会自动扫描并将其纳入容器管理),同时确保dataSource的注入正确:
@Repository public class EmployeeDAO { @Autowired @Qualifier("dataSource") private DataSource dataSource; public List<Map<String,Object>> viewEmployees() { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); List<Map<String, Object>> rows = jdbcTemplate.queryForList("SELECT * FROM employee"); return rows; } }
2. 在EmployeeServiceImpl中注入EmployeeDAO(而非手动new)
把EmployeeDAO作为依赖注入到Service层,推荐用构造器注入(这是Spring官方推荐的依赖注入方式,更安全且符合最佳实践):
@Service public class EmployeeServiceImpl { private final EmployeeDAO employeeDAO; // 构造器注入,Spring会自动从容器中获取EmployeeDAO实例注入进来 public EmployeeServiceImpl(EmployeeDAO employeeDAO) { this.employeeDAO = employeeDAO; } public List<Employee> viewEmployees(){ List<Employee> employees = new ArrayList<>(); List<Map<String, Object>> rows = employeeDAO.viewEmployees(); // 遍历转换Map到Employee实体 for (Map<String, Object> row : rows) { Employee employee = new Employee(); employee.setId((Integer) row.get("id")); employee.setName((String) row.get("name")); employee.setPosition((String) row.get("position")); employee.setProvision_goal((Integer) row.get("provision_goal")); employee.setProvision_accumulated((Integer) row.get("provision_accumulated")); employees.add(employee); } return employees; } }
3. 额外优化:直接返回Employee实体列表(简化代码)
其实你完全可以不用手动把Map转换成Employee对象,JdbcTemplate支持直接返回实体类列表。修改EmployeeDAO的方法如下:
@Repository public class EmployeeDAO { @Autowired @Qualifier("dataSource") private DataSource dataSource; public List<Employee> viewEmployees() { String sql = "SELECT * FROM employee"; JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); // 使用BeanPropertyRowMapper自动映射查询结果到Employee实体 return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Employee.class)); } }
这样EmployeeServiceImpl的代码可以简化成:
@Service public class EmployeeServiceImpl { private final EmployeeDAO employeeDAO; public EmployeeServiceImpl(EmployeeDAO employeeDAO) { this.employeeDAO = employeeDAO; } public List<Employee> viewEmployees(){ // 直接返回DAO层拿到的Employee列表,无需手动转换 return employeeDAO.viewEmployees(); } }
总结
只要让DAO和Service都交给Spring容器管理,通过依赖注入获取实例(而不是自己手动new),不仅能解决数据源注入的错误,DAO层的查询结果也能正常传递到Service层。
内容的提问来源于stack exchange,提问作者Josef Brøndum Schmidt

