MyBatis 的 Mapper 接口实际上并不需要我们手动去写实现类,它的工作方式有点像“魔法”,但背后是扎实的框架机制在支撑。简单来说,MyBatis 通过动态代理,在运行时生成接口的实现类,并将 SQL 语句绑定到这些实现类的方法上。
解决方案:
MyBatis 的 Mapper 接口工作流程主要依赖于以下几个核心机制:
-
接口定义: 首先,你需要定义一个 Mapper 接口,这个接口中的方法对应着你想要执行的 SQL 操作。接口方法可以接受参数,也可以返回结果。
public interface UserMapper { User getUserById(int id); List<User> getAllUsers(); void insertUser(User user); void updateUser(User user); void deleteUser(int id); }
-
SQL 映射文件: 然后,你需要创建一个 XML 映射文件,这个文件与 Mapper 接口对应,并且包含了 SQL 语句和接口方法之间的映射关系。
<mapper namespace="com.example.UserMapper"> <select id="getUserById" parameterType="int" resultType="com.example.User"> SELECT * FROM users WHERE id = #{id} </select> <select id="getAllUsers" resultType="com.example.User"> SELECT * FROM users </select> <insert id="insertUser" parameterType="com.example.User"> INSERT INTO users (name, email) VALUES (#{name}, #{email}) </insert> <update id="updateUser" parameterType="com.example.User"> UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id} </update> <delete id="deleteUser" parameterType="int"> DELETE FROM users WHERE id = #{id} </delete> </mapper>
动态代理: 当你通过
SqlSession
获取 Mapper 接口的实例时,MyBatis 会使用 JDK 动态代理(或者 CGLIB,如果接口没有实现)创建一个代理对象。这个代理对象会拦截所有对接口方法的调用。方法拦截和 SQL 执行: 当代理对象拦截到方法调用时,它会根据方法名和参数,在 XML 映射文件中查找对应的 SQL 语句。然后,它会使用
SqlSession
执行 SQL 语句,并将结果映射到相应的 Java 对象。结果返回: 最后,代理对象会将执行结果返回给调用者。
为什么没有实现类?因为 MyBatis 在运行时动态生成了实现类。 这避免了大量重复的样板代码,也使得代码更加简洁和易于维护。想象一下,如果每个 Mapper 接口都要手动写一个实现类,那将会是一场噩梦。
MyBatis 如何加载和解析 Mapper 映射文件?MyBatis 通过
SqlSessionFactoryBuilder构建
SqlSessionFactory,在构建过程中,会解析 MyBatis 的配置文件 (mybatis-config.xml),其中会包含 Mapper 映射文件的位置。
具体来说,MyBatis 会使用
XMLConfigBuilder解析配置文件,并使用
XMLMapperBuilder解析 Mapper 映射文件。
XMLMapperBuilder会读取 XML 文件,并将其中的 SQL 语句、参数映射、结果映射等信息解析成 MyBatis 内部的数据结构,例如
MappedStatement。这些
MappedStatement对象会被存储在
Configuration对象中,供后续的 SQL 执行使用。
如果你的Mapper文件没有正确加载,可能会遇到
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)错误。 检查你的 mybatis-config.xml 文件,确保Mapper文件路径正确,并且文件存在。 另外,检查Mapper接口的namespace是否和Mapper文件的namespace一致。 如何在 Spring Boot 中集成 MyBatis 并使用 Mapper 接口?
Spring Boot 提供了
mybatis-spring-boot-starter依赖,可以方便地集成 MyBatis。

全面的AI聚合平台,一站式访问所有顶级AI模型


-
添加依赖: 首先,需要在
pom.xml
文件中添加mybatis-spring-boot-starter
依赖。<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.0</version> <!-- 请使用最新版本 --> </dependency>
-
配置数据源: 然后,需要在
application.properties
或application.yml
文件中配置数据源信息,例如数据库连接 URL、用户名、密码等。spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase spring.datasource.username=root spring.datasource.password=password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
-
配置 MyBatis: 接下来,可以在
application.properties
或application.yml
文件中配置 MyBatis 的相关属性,例如 Mapper 接口的扫描路径、配置文件的位置等。mybatis.mapper-locations=classpath:mapper/*.xml mybatis.configuration.map-underscore-to-camel-case=true
-
使用 Mapper 接口: 最后,可以使用
@Autowired
注解将 Mapper 接口注入到你的 Service 或 Controller 中,并直接调用接口方法执行 SQL 操作。@Service public class UserService { @Autowired private UserMapper userMapper; public User getUserById(int id) { return userMapper.getUserById(id); } }
注意, Spring Boot 会自动扫描 Mapper 接口,并将其注册为 Spring Bean。 如果你没有看到你的Mapper Bean被注入,检查你的启动类是否添加了
@MapperScan注解,并指定正确的 Mapper 接口扫描路径。 例如:
@MapperScan("com.example.mapper")MyBatis 的动态 SQL 是如何实现的?它有哪些常用的标签?
MyBatis 的动态 SQL 功能允许你根据不同的条件动态生成 SQL 语句,这在处理复杂的查询场景时非常有用。 动态 SQL 的实现依赖于 MyBatis 提供的各种标签,例如
<if>,
<choose>,
<when>,
<otherwise>,
<where>,
<set>,
<foreach>等。
-
<if>
: 用于根据条件判断是否包含某段 SQL 片段。<select id="findActiveBlogWithTitleLike" resultType="Blog"> SELECT * FROM blog WHERE state = ‘ACTIVE’ <if test="title != null"> AND title like #{title} </if> </select>
-
<choose>
,<when>
,<otherwise>
: 类似于 Java 中的switch
语句,用于根据不同的条件选择不同的 SQL 片段。<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM blog WHERE state = ‘ACTIVE’ <choose> <when test="title != null"> AND title like #{title} </when> <when test="author != null and author.name != null"> AND author_name like #{author.name} </when> <otherwise> AND featured = 1 </otherwise> </choose> </select>
-
<where>
: 用于自动添加WHERE
关键字,并且可以智能地处理AND
或OR
关键字的开头问题。<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM blog <where> state = ‘ACTIVE’ <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </where> </select>
-
<set>
: 用于在UPDATE
语句中动态设置字段,并且可以智能地处理逗号的问题。<update id="updateAuthorIfNecessary"> update Author <set> <if test="username != null">username=#{username},</if> <if test="password != null">password=#{password},</if> <if test="email != null">email=#{email},</if> bio=#{bio} </set> where id=#{id} </update>
-
<foreach>
: 用于遍历集合,可以生成IN
语句或者批量插入语句。<select id="selectPostIn" resultType="Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>
在使用动态 SQL 时,需要注意 SQL 注入的风险。 尽量使用
#占位符,而不是
${}字符串替换。
#占位符可以防止 SQL 注入,因为它会将参数值作为预编译语句的参数传递给数据库,而不是直接拼接到 SQL 语句中。
以上就是MyBatis 的Mapper接口是如何工作的?为什么没有实现类?的详细内容,更多请关注知识资源分享宝库其它相关文章!
相关标签: mysql word java apache app ai switch sql语句 Java sql spring spring boot mybatis if switch foreach xml 字符串 数据结构 接口 Namespace 对象 数据库 apache 大家都在看: MyBatis终极性能优化:让你的数据库操作快人一步 MyBatis 的Mapper接口是如何工作的?为什么没有实现类? java使用教程如何使用MyBatis操作数据库 java使用教程的MyBatis应用方法 java如何使用MyBatis操作数据库 java持久层框架的实用编程方法 MyBatis批量插入数据详细优化方案
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。