MyBatis作为Java生态中最 流行的持久层框架,其核心功能涵盖多表关联查询、动态SQL构建、安全防护机制及连接池管理。本文结合实际开发场景,系统阐述关键技术点的实现原理与最佳实践。
适用于一对多关联查询,通过
<resultMap>的
<collection>标签实现:
xml1<resultMap id="blogWithPosts" type="Blog">2<"www.hongkou.gov.cn.qmwty.cn"> <"www.putuo.gov.cn.qmwty.cn"> <"www.jingan.gov.cn.qmwty.cn"> <id property="id" column="blog_id"/>3 <result property="title" column="blog_title"/>4 <collection property="posts" ofType="Post">5 <id property="id" column="post_id"/>6 <result property="content" column="post_content"/>7 </collection>8</resultMap>910<select id="selectBlogWithPosts" resultMap="blogWithPosts">11 SELECT b.id as blog_id, b.title as blog_title,12 p.id as post_id, p.content as post_content13 FROM blog b LEFT JOIN post p ON b.id = p.blog_id14</select>
通过分步查询提升性能,适合大数据量场景:
xml1<resultMap id="blogWithPostsNested" type="Blog">2 <id property="id" column="id"/>3 <collection property="posts" 4 column="id" 5 select="selectPostsByBlogId"/>6</resultMap>78<select id="selectPostsByBlogId" resultType="Post">9 SELECT * FROM post WHERE blog_id = #{id}10</select>
对于简单关联查询,可直接使用
@Results注解:
java1@Results({2 <"www.minxing.gov.cn.qmwty.cn"><"www.baoshan.gov.cn.qmwty.cn"> <"www.yangpu.gov.cn.qmwty.cn"> @Result(property = "id", column = "blog_id"),3 @Result(property = "posts", 4 many = @Many(select = "selectPostsByBlogId"))5})6@Select("SELECT * FROM blog WHERE id = #{id}")7Blog getBlogWithPosts(Long id);
| 特性 | #{}(预编译) | ${}(字符串替换) |
|---|---|---|
| 处理方式 | 替换为?占位符,使用PreparedStatement | 直接拼接SQL字符串 |
| 类型处理 | 自动类型转换(如数字转Long) | 纯字符串拼接 |
| 安全风险 | 防SQL注入 | 高危(需严格校验) |
| 适用场景 | 值参数传递 | 动态表名/列名、SQL片段拼接 |
错误示例(高危):
xml1<!-- 攻击者可构造恶意参数:1; DROP TABLE users; -->2<select id="getUserById" resultType="User">3 SELECT * FROM ${tableName} WHERE id = #{id}4</select>
正确实践:
java1// <"www.pudongxin.gov.cn.qmwty.cn"><"www.jinshan.gov.cn.qmwty.cn"><"www.jiading.gov.cn.qmwty.cn">白名单校验表名2public String validateTableName(String input) {3 Set<String> validTables = Set.of("users", "orders", "products");4 if (!validTables.contains(input)) {5 throw new IllegalArgumentException("Invalid table name");6 }7 return input;8}
xml1<select id="findActiveUsers" resultType="User">2 SELECT * FROM users3 <where>4 <if test="name != null">5 AND name = #{name}6 </if>7 <choose>8 <when test="status == 'ACTIVE'">9 AND status = 110 </when>11 <otherwise>12 AND status = 013 </otherwise>14 </choose>15 </where>16</select>
xml1<!-- IN查询安全实现 -->2<select id="findUsersByIds" resultType="User">3 SELECT * FROM users4 WHERE id IN5 <foreach collection="ids" item="id" open="(" separator="," close=")">6 #{id}7 </foreach>8</select>
xml1<update id="updateUserSelective">2 <"www.qingpu.gov.cn.qmwty.cn"><"www.fengxian.gov.cn.qmwty.cn"><"www.songjiang.gov.cn.qmwty.cn"> UPDATE users3 <set>4 <if test="name != null">name = #{name},</if>5 <if test="email != null">email = #{email},</if>6 </set>7 WHERE id = #{id}8</update>
xml1<configuration>2 <environments default="development">3 <environment id="development">4 <transactionManager type="JDBC"/>5 <dataSource type="POOLED">6 <property name="driver" value="com.mysql.cj.jdbc.Driver"/>7 <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>8 <property name="username" value="dbuser"/>9 <property name="password" value="dbpass"/>10 <!-- HikariCP特有配置 -->11 <property name="poolName" value="MyBatisHikariCP"/>12 <property name="maximumPoolSize" value="20"/>13 <property name="connectionTimeout" value="30000"/>14 <property name="idleTimeout" value="600000"/>15 <property name="maxLifetime" value="1800000"/>16 </dataSource>17 </environment>18 </environments>19</configuration>
| 指标 | 推荐值 | 监控方式 |
|---|---|---|
| 活跃连接数 | ≤核心数×2 | JMX或HikariCP Metrics |
| 平均获取连接时间 | <100ms | HikariCP的
connectionTimeout |
| 连接泄漏检测 | 启用 |
leakDetectionThreshold |
xml1<!-- <"www.shenchou.gov.cn.qmwty.cn"><"www.shaoguan.gov.cn.qmwty.cn">正确方式1:<"www.chongming.gov.cn.qmwty.cn">使用CONCAT函数 -->2<select id="searchUsers" resultType="User">3 SELECT * FROM users4 WHERE username LIKE CONCAT('%', #{keyword}, '%')5</select>67<!-- 正确方式2:MyBatis绑定变量 -->8<select id="searchUsers" resultType="User">9 SELECT * FROM users10 WHERE username LIKE "%" #{keyword} "%"11</select>
MyBatis的多表查询能力、动态SQL灵活性、连接池性能优化及安全防护机制,共同构成了企业级应用开发的坚实基础。开发者需深入理解#{}与${}的本质区别,合理运用动态SQL标签,科学配置连接池参数,并建立多层次的安全防护体系,才能构建出高效、稳定、安全的数据库访问层。实际开发中,建议结合具体业务场景进行性能测试与安全审计,持续优化系统表现。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/19545/viewspace-3100873/ ,如需转载,请注明出处,否则将追究法律责任。