SSM(Spring + SpringMVC + MyBatis)作为经典的Java Web开发组合,其核心功能之一便是高效、稳定地从数据库中存取数据,理解其取数据的完整流程,对于掌握SSM框架乃至进行后续的优化与排错都至关重要,下面,我们将深入剖析这一过程,从请求发起到数据返回的每一个环节。
SSM框架取数据核心流程
SSM框架通过分层解耦的设计,将数据处理职责清晰地划分在不同层面,其取数据流程主要涉及表现层、业务逻辑层和持久化层的协同工作。
层级 | 核心组件 | 主要职责 |
---|---|---|
表现层 | SpringMVC Controller | 接收前端请求,调用Service层,处理响应数据,返回视图。 |
业务逻辑层 | Service Interface & Impl | 实现核心业务逻辑,组装数据,调用持久化层接口,管理事务。 |
持久化层 | MyBatis Mapper Interface & XML | 定义数据库操作接口,编写SQL语句,与数据库直接交互,完成数据映射。 |
详细步骤解析
假设一个场景:用户在前端页面上点击一个按钮,请求查询ID为1的用户信息,整个取数据过程如下:
请求的发起与接收
用户操作触发前端发送一个HTTP请求,GET /user/getUser?id=1
,这个请求首先被SpringMVC的核心控制器DispatcherServlet
拦截。DispatcherServlet
根据请求的URL(/user/getUser
),查找并匹配到对应的Controller
处理方法,一个使用@RequestMapping("/user/getUser")
注解的方法。
@Controller @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @RequestMapping("/getUser") public ModelAndView getUser(int id) { User user = userService.findUserById(id); ModelAndView mv = new ModelAndView(); mv.addObject("user", user); mv.setViewName("userDetail"); return mv; } }
业务逻辑的调用
Controller
接收到请求参数(如id=1
)后,它本身并不直接操作数据库,它的职责是调用业务逻辑层,即UserService
,通过Spring的依赖注入(@Autowired
),UserController
获得了UserService
的实例,并调用其findUserById(id)
方法,这种设计将业务逻辑与Web请求处理分离开,提高了代码的复用性和可维护性。
@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; // 持久化层接口 @Override public User findUserById(int id) { // 这里可以添加额外的业务逻辑,如数据校验、权限判断等 return userMapper.selectByPrimaryKey(id); } }
数据持久化的执行
这是与数据库直接交互的关键一步。Service
层调用了UserMapper
接口中的方法。UserMapper
是一个MyBatis的Mapper接口,它只定义了方法签名,而没有实现。
@Mapper // 或者在Spring配置文件中通过MapperScannerConfigurer扫描 public interface UserMapper { User selectByPrimaryKey(int id); }
selectByPrimaryKey
方法是如何被执行的呢?这背后是MyBatis与Spring整合的“魔法”:
- 动态代理: Spring在启动时,会为
UserMapper
接口创建一个动态代理对象,当Service
层调用userMapper.selectByPrimaryKey(id)
时,实际上是在调用这个代理对象的方法。 - SQL映射: 代理对象会根据当前调用的方法名(
selectByPrimaryKey
)和接口全限定名,去寻找与之对应的SQL语句,这个映射关系定义在UserMapper.xml
文件中。
<!-- UserMapper.xml --> <mapper namespace="com.example.mapper.UserMapper"> <select id="selectByPrimaryKey" resultType="com.example.model.User"> SELECT * FROM user WHERE id = #{id} </select> </mapper>
- SQL执行: 找到SQL后,MyBatis会通过
SqlSession
来执行这条查询语句。#{id}
会被替换成一个预编译参数(),有效地防止了SQL注入,数据库接收到SQL并执行查询。 - 结果处理: 数据库返回查询结果集,MyBatis根据
resultType
(或resultMap
)的配置,将结果集中的每一行数据自动映射成一个User
对象。
结果的封装与返回
MyBatis将User
对象返回给Service
层的调用点。Service
层可以对这个对象进行进一步处理,然后将其返回给Controller
。Controller
接收到User
对象后,将其存入ModelAndView
对象中,以便后续视图渲染使用。
视图的渲染
Controller
返回ModelAndView
后,DispatcherServlet
会根据配置的视图解析器(ViewResolver
)找到对应的视图文件(例如userDetail.jsp
),在JSP页面中,可以通过EL表达式(如${user.name}
)来获取并显示从数据库查询出的用户信息,最终生成完整的HTML页面返回给浏览器。
关键配置要点
要让上述流程顺畅运行,正确的配置是必不可少的。
配置文件 | 关键配置项 | 作用说明 |
---|---|---|
Spring配置文件 | DataSource | 配置数据库连接信息,包括URL、用户名、密码、驱动等。 |
SqlSessionFactoryBean | MyBatis的核心工厂,负责创建SqlSession ,需要注入DataSource 并指定Mapper XML文件的位置。 | |
MapperScannerConfigurer | 自动扫描指定包路径下的Mapper接口,将其注册为Spring Bean,以便在Service层进行注入。 | |
SpringMVC配置文件 | <context:component-scan> | 扫描@Controller , @Service 等注解,将它们注册为Spring容器中的Bean。 |
ViewResolver | 视图解析器,负责将逻辑视图名(如”userDetail”)解析为具体的物理视图资源(如/WEB-INF/jsp/userDetail.jsp )。 |
通过这种层层调用、职责分明的协作模式,SSM框架优雅地实现了从数据库取数据的全过程,不仅流程清晰,而且各层之间松耦合,便于开发、测试和维护。
相关问答 (FAQs)
问:在MyBatis的SQL映射文件中,和 有什么区别?
答: 这是MyBatis中一个非常关键的区别,直接关系到应用的安全性。
- 这是预编译处理,也就是PreparedStatement,MyBatis在处理时,会将SQL中的替换为占位符,然后使用
PreparedStatement
的setXxx()
方法来设置参数值,这种方式可以有效防止SQL注入,是推荐使用的参数传递方式。 - 这是字符串替换,MyBatis在处理时,会直接将中的字符串原封不动地拼接到SQL语句中,这种方式无法防止SQL注入,存在极大的安全风险,它通常用于需要动态传入表名、列名等非参数值的场景,并且这些值必须是程序内部可控的,绝不能用于接收用户输入。
问:MyBatis是如何将数据库查询结果自动映射到Java对象的?
答: MyBatis提供了强大的结果映射机制,主要分为两种:
- 自动映射(Auto-mapping): 这是最简单的映射方式,当查询结果的列名(如
user_name
)与Java对象(POJO)的属性名(如userName
)相匹配时,MyBatis会自动完成映射,它还支持驼峰命名转换,即在配置中开启mapUnderscoreToCamelCase
后,user_name
列可以自动映射到userName
属性。 - 手动映射(ResultMap): 当列名和属性名不匹配,或者需要进行复杂的映射(如一对一、一对多关联查询)时,就需要使用
<resultMap>
标签,通过<resultMap>
,你可以显式地定义数据库列与Java对象属性之间的对应关系,提供完全的控制权,处理各种复杂的映射场景,可以将数据库的id
列映射到对象的userId
属性。
【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!
发表回复