mybatis的${}和#{}的区别
底层 类型转换 单个简单类的参数 防止sql注入
#{} preparedStatement 转换 #{sb} 防止
{} statement 不转换 {value} 不防止
一、ORM映射(字段与POJO属性匹配)
-
字段起别名 核心逻辑:在SQL语句中为数据库字段起别名,别名必须和POJO的属性名完全一致。 示例: ```sql SELECT id, role_name roleName, role_desc roleDesc FROM role ``` - **适用场景**:字段名与属性名仅少量不一致,场景简单。
-
结果映射ResultMap 核心作用:解决字段名与POJO属性名不一致问题(比别名更灵活,支持复杂场景)。
核心标签&属性:<resultMap>` | 定义映射关系 | `id`(唯一标识)、`type`(POJO全类名)
`<id>` | 映射主键字段 | `column`(表字段名)、`property`(POJO属性名)
`<result>` | 映射普通字段 | `column`(表字段名)、`property`(POJO属性名)
示例:xml <resultMap id="findUserResultMap" type="com.hg.pojo.Role">
<id column="id" property="id"/> <!-- 主键 -->
<result column="role_name" property="roleName"/> <!-- 普通字段 -->
</resultMap>
<select id="findUser" resultMap="findUserResultMap">
SELECT id, role_name, role_desc FROM role
</select>
二、MyBatis别名配置
- 内置别名 - 四类八种基本类型(如int、long、boolean)、集合接口(如list、map),
全部小写 即可直接使用(无需写全类名)。
- 自定义别名(简化全类名书写) | 配置方式 | 标签/属性 | 示例
单个定义 | `<typeAlias>` | `<typeAlias type="com.hg.pojo.User" alias="user"/>` | |
批量定义(推荐)<package>` | `<typeAliases><package name="com.hg.pojo"/></typeAliases>` | 效果:配置后,XML中可直接用别名(如`user`)代替全类名(`com.hg.pojo.User`)。
三、Mapper配置文件批量引入 核心标签:`
<mappers>`(在mybatis-config.xml中配置)用于指定MyBatis要加载的Mapper映射文件/接口。 单个映射文件(XML)<mapper resource="路径"/>` | `
<mapper resource="com/hg/mapper/RoleMapper.xml"/>` | 路径以`/`分隔,需写完整XML文件名 | |
单个Mapper接口 | `<mapper class="全类名"/>` | `<mapper class="com.hg.mapper.RoleMapper"/>` | 接口与XML需同目录、同名 | | 批量引入Mapper接口(推荐)
| `<package name="包名"/>` | `<package name="com.hg.mapper"/>` | 所有接口需在指定包下,且接口与XML同目录、同名 | ##
四、关联查询(多表查询) 核心:
通过`<resultMap>`结合`<association>`/`<collection>`映射多表关联结果,解决字段与POJO属性不匹配问题。 ###
- 一对一(如Account→User) -
**POJO设计**:在主实体(Account)中包含关联实体(User)的属性。 ```
java public class Account { private Integer id; private Double money; private User user; // 一对一关联属性 } ``` - *
*ResultMap配置**: ```xml <resultMap id="findAccountByIdResultMap" type="com.hg.pojo.Account"> <id column="aid" property="id"/> <result column="money" property="money"/> <!-- 一对一映射:javaType指定关联实体的全类名 --> <association property="user" javaType="com.hg.pojo.User"> <id column="uid" property="id"/> <result column="username" property="username"/> </association> </resultMap> ``` ###
- 一对多(如User→List<Account>) -
**POJO设计**:在主实体(User)中包含关联实体的集合属性。 ```java public class User { private Integer id; private String username; private List<Account> accountList; // 一对多关联属性 } ``` - **ResultMap配置**: ```xml <resultMap id="findUserByIdResultMap" type="com.hg.pojo.User"> <id column="uid" property="id"/> <result column="username" property="username"/> <!--
一对多映射:ofType指定集合泛型的全类名 --> <collection property="accountList" ofType="com.hg.pojo.Account"> <id column="aid" property="id"/> <result column="money" property="money"/> </collection> </resultMap> ```
3. 多对多(如Role→List<User>) - **本质**:拆解为"一对多"处理(借助中间表)。
- **POJO设计**:在主实体(Role)中包含关联实体(User)的集合属性。 ```java public class Role { private Integer id; private String roleName; private List<User> userList; // 多对多关联属性(本质是一对多) } ``` - **ResultMap配置**:与"一对多"一致,使用`<collection>`标签,`ofType`指定泛型全类名。 ##
五、延迟加载(懒加载) ###
-
核心作用 - 按需加载数据:查询主实体时不加载关联数据,只有调用关联属性时才执行关联SQL,提升查询性能。 ###
-
配置方式(基于ResultMap) ```xml <resultMap id="findUserByIdResultMap" type="com.hg.pojo.User"> <id column="id" property="id"/> <result column="username" property="username"/> <!-- 懒加载配置 --> <collection property="accountList" <!-- 关联属性名 --> ofType="com.hg.pojo.Account" <!-- 集合泛型全类名 --> select="com.hg.mapper.AccountMapper.findAccountByUid" <!-- 关联SQL的全限定名 --> column="id" <!-- 传递给关联SQL的参数(主表字段) --> fetchType="lazy"> <!-- lazy=懒加载,eager=立即加载 --> </collection> </resultMap> ``` ###
总结
- **ORM映射核心**:简单场景用字段别名,复杂场景(多字段/多表)必须用`ResultMap`; 2. **关联查询关键**:一对一用`<association>`(指定`javaType`),一对多/多对多用`<collection>`(指定`ofType`); 3. **简化配置技巧**:别名批量配置、Mapper文件批量引入,懒加载按需提升性能。