Spring中DAO层Mapper空指针错误的解决方法咨询
Mapper空指针问题排查与解决
问题背景
已在Dispatcher Servlet.xml中为Mapper接口和DAO构建Bean,新建Mapper包并添加接口,同时实现了DAO;在DAO中通过Dispatcher Servlet内的DAO Bean与Mapper构建服务;在Controller中使用@Autowired和@Qualifier注入DAO,但仍遭遇Mapper空指针错误,相关Controller代码如下:
package Controller; import java.util.List; import org.apache.ibatis.session.SqlSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import DAO.CourseStudentDAO; import DAO.CourseDAO; import DAO.StudentDAO; import DTO.CourseResponseDTO; import DTO.CourseStudentRequestDTO; import DTO.StudentRequestDTO; import DTO.StudentResponseDTO; import Model.StudentBean; @Controller public class StudentController { @Autowired @Qualifier("sqlSession") SqlSession session; @Autowired @Qualifier("courseStudentDAO") private CourseStudentDAO CourseStudentDAO; @Autowired @Qualifier("courseDAO") private CourseDAO CourseDAO; @Autowired @Qualifier("studentDAO") private StudentDAO StudentDAO; @RequestMapping(value="/studentaddpage",method=RequestMethod.GET) public ModelAndView studentaddpage(ModelMap model) { CourseDAO.selectAll(); List<CourseResponseDTO> courseList = CourseDAO.selectAll(); model.addAttribute("courseList", courseList); return new ModelAndView("STU001", "studentbean", new StudentBean()); } @RequestMapping(value = "/StudentAddPage", method = RequestMethod.POST) public String addStu(@ModelAttribute("studentbean") @Validated StudentBean studentbean, ModelMap model) { //insert List<String> attendArray = studentbean.getCourse(); if (studentbean.getStudentname().isBlank() || studentbean.getDob().isBlank() || studentbean.getGender().isBlank()||studentbean.getPhone().isBlank() ||studentbean.getEducation().isBlank() ||studentbean.getStudentid().isBlank()) { model.addAttribute("errorFill", "Fill the Blank!!!"); return "redirect:/studentaddpage"; }else { StudentDAO dao = new StudentDAO(); StudentResponseDTO res = new StudentResponseDTO(); StudentRequestDTO dto = new StudentRequestDTO(); DAO.CourseStudentDAO csdao = new DAO.CourseStudentDAO(); CourseStudentRequestDTO csdto = new CourseStudentRequestDTO(); for(String a : attendArray ) { csdto.setStudentid(studentbean.getStudentid()); csdto.setCourse(a); csdao.insert(csdto); } dto.setStudentid(studentbean.getStudentid()); dto.setStudentname(studentbean.getStudentname()); dto.setDob(studentbean.getDob()); dto.setGender(studentbean.getGender()); dto.setPhone(studentbean.getPhone()); dto.setEducation(studentbean.getEducation()); dao.insert(dto); session.commit(); return "redirect:/studentsearchpage"; } } //show&search @RequestMapping(value = "/studentsearchpage", method = RequestMethod.GET) public ModelAndView stuSearchPage(ModelMap model) { StudentDAO dao = new StudentDAO(); CourseStudentDAO csdao = new CourseStudentDAO(); List<StudentResponseDTO> list = dao.selectAll(); for(StudentResponseDTO a : list) { List<String> courselist = csdao.selectOne(a.getStudentid()); a.setCourse(courselist); } model.addAttribute("studentList", list); return new ModelAndView("STU003", "studentbean", new StudentBean()); } @RequestMapping(value = "/StudentSearchPage", method = RequestMethod.POST) public ModelAndView searchStudent(@ModelAttribute("studentbean") StudentBean studentbean, ModelMap model) { StudentRequestDTO req = new StudentRequestDTO(); req.setStudentid(studentbean.getSearchid()); req.setStudentname(studentbean.getSearchname()); CourseStudentDAO csdao = new CourseStudentDAO(); StudentDAO dao = new StudentDAO(); if(dao.search(req).isEmpty()) { return new ModelAndView("STU003", "studentbean", new StudentBean()); } else { List<StudentResponseDTO> list = dao.search(req); for(StudentResponseDTO a : list) { List<String> courselist = csdao.selectOne(a.getStudentid()); a.setCourse(courselist); } model.addAttribute("studentList", list); List<StudentResponseDTO> dto=dao.search(req); return new ModelAndView("STU003", "studentbean", new StudentBean()); } } //Student Update @RequestMapping(value="/studentupdatedpage/{studentid}" ,method=RequestMethod.GET) public ModelAndView studentupdatepage(@PathVariable String studentid,ModelMap model) { StudentRequestDTO dto=new StudentRequestDTO(); dto.setStudentid(studentid); CourseDAO.selectAll(); List<CourseResponseDTO> courseList = CourseDAO.selectAll(); model.addAttribute("courseList", courseList); return new ModelAndView("STU002","studentbean",StudentDAO.selectOne(dto)); } @RequestMapping(value = "/studentupdatedpage/UpdateStudentUpdatePage" , method = RequestMethod.POST) public String updateStu(@ModelAttribute("studentbean")StudentBean studentbean,ModelMap model) { List<String> attendArray = studentbean.getCourse(); if (studentbean.getStudentname().isBlank() || studentbean.getDob().isBlank() || studentbean.getGender().isBlank()||studentbean.getPhone().isBlank() ||studentbean.getEducation().isBlank() ||studentbean.getStudentid().isBlank() ) { model.addAttribute("errorFill", "Fill the Blank!!!"); model.addAttribute("studentbean", studentbean); return "redirect:/studentupdatedpage"; } else { StudentResponseDTO res = new StudentResponseDTO(); StudentRequestDTO dto = new StudentRequestDTO(); StudentDAO dao=new StudentDAO(); CourseStudentDAO csdao = new CourseStudentDAO(); CourseStudentRequestDTO csdto = new CourseStudentRequestDTO(); csdto.setStudentid(studentbean.getStudentid()); csdao.delete(csdto); for(String a : attendArray ) { csdto.setStudentid(studentbean.getStudentid()); csdto.setCourse(a); csdao.insert(csdto); } dto.setStudentid(studentbean.getStudentid()); dto.setStudentname(studentbean.getStudentname()); dto.setDob(studentbean.getDob()); dto.setGender(studentbean.getGender()); dto.setPhone(studentbean.getPhone()); dto.setEducation(studentbean.getEducation()); dao.update(dto); return "redirect:/studentsearchpage"; } } @RequestMapping(value = "/DeleteStudent/{studentid}", method = RequestMethod.GET) public String deleteStu(@PathVariable String studentid, ModelMap model) { StudentDAO dao=new StudentDAO(); StudentRequestDTO dto = new StudentRequestDTO(); CourseStudentDAO csdao = new CourseStudentDAO(); CourseStudentRequestDTO csdto = new CourseStudentRequestDTO(); dto.setStudentid(studentid); csdto.setStudentid(studentid); dao.delete(dto); csdao.delete(csdto); model.addAttribute("errorFill", "Success delete"); return "redirect:/stuSearchPage"; } }
问题根源
代码核心错误是在方法内部手动new了DAO实例(比如StudentDAO dao = new StudentDAO();、CourseStudentDAO csdao = new CourseStudentDAO();),这些手动创建的对象未被Spring容器管理,内部的Mapper依赖不会被注入,调用方法时必然触发空指针异常。
而类顶部通过@Autowired注入的StudentDAO、CourseStudentDAO等实例才是被Spring管理、完成依赖注入的对象,应该直接使用这些对象。
修复步骤
- 删除所有手动new DAO的代码,直接使用类中已注入的DAO成员变量
- 确保DAO实现类中,Mapper是通过Spring注入(比如
@Autowired注入Mapper接口)或者通过Spring管理的SqlSession获取(sqlSession.getMapper(XXXMapper.class)) - 建议使用Spring声明式事务管理,替代手动调用
session.commit(),避免事务管理混乱
修改后的核心代码示例
以addStu方法为例,修改后如下:
@RequestMapping(value = "/StudentAddPage", method = RequestMethod.POST) public String addStu(@ModelAttribute("studentbean") @Validated StudentBean studentbean, ModelMap model) { List<String> attendArray = studentbean.getCourse(); if (studentbean.getStudentname().isBlank() || studentbean.getDob().isBlank() || studentbean.getGender().isBlank()||studentbean.getPhone().isBlank() ||studentbean.getEducation().isBlank() ||studentbean.getStudentid().isBlank()) { model.addAttribute("errorFill", "Fill the Blank!!!"); return "redirect:/studentaddpage"; } else { StudentRequestDTO dto = new StudentRequestDTO(); CourseStudentRequestDTO csdto = new CourseStudentRequestDTO(); for(String a : attendArray ) { csdto.setStudentid(studentbean.getStudentid()); csdto.setCourse(a); // 使用注入的CourseStudentDAO CourseStudentDAO.insert(csdto); } dto.setStudentid(studentbean.getStudentid()); dto.setStudentname(studentbean.getStudentname()); dto.setDob(studentbean.getDob()); dto.setGender(studentbean.getGender()); dto.setPhone(studentbean.getPhone()); dto.setEducation(studentbean.getEducation()); // 使用注入的StudentDAO StudentDAO.insert(dto); session.commit(); return "redirect:/studentsearchpage"; } }
其他方法如stuSearchPage、updateStu、deleteStu都需要做同样的修改:删除new DAO实例的代码,直接使用类顶部注入的对象。
内容的提问来源于stack exchange,提问作者Minthway Khaing
相关产品推荐
相关产品推荐

