准备工作
-
相关maven依赖
LombokSpring WebMyBatis FrameworkMySQL Driver -
application.properties 配置数据源
spring.datasource.url=jdbc:mysql://localhost:3306/myapp_db
spring.datasource.username=xxx
spring.datasource.password=xxx
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# resources目录下新建mapper目录
mybatis.mapper-locations=classpath:mapper/**.xml
# 数据库表列明 中横线转 表实体bean对应的小驼峰
mybatis.configuration.map-underscore-to-camel-case=true
# 开启sql日志
logging.level.org.example.mybatis.mapper=debug
- idea安装
mybatisx插件, 按键自动生成Mapper接口对应的xml实现
取值
#{}安全的参数预编译
${}是直接的字符串拼接。
| 特性 | #{} (井号占位符) | ${} (美元占位符) |
|---|---|---|
| 处理方式 | 预编译(PreparedStatement) ,参数化查询 | 字符串拼接(Statement) ,直接替换 |
| 安全性 | 高,有效防止SQL注入 | 低,存在SQL注入风险 |
| 参数类型 | 任意类型,自动进行类型转换和转义 | 通常为字符串,原样替换,不转义 |
| 使用场景 | 几乎所有的值传递(WHERE条件值、INSERT值等) | 动态SQL片段(表名、列名、ORDER BY等) |
取入参值
- 当只有一个参数时,直接放变量名(xml中的变量名可以随便命名) 或 bean中属性, 这时可以不用
@Param;若用了@Param,xml中的变量名必须和@Param内的命名保持一致,不能直接取bean中属性,需要@Param内的命名.属性名
@Mapper
public interface UserMapper {
User getUserById(String id);
void insertUser(User user);
}
<select id="getUserById" resultType="org.example.mybatis.entity.User">
select * from users where id = #{id}
</select>
<!-- username email 为 User 中的属性 -->
<insert id="insertUser">
insert into users(username, email)values (#{username}, #{email})
</insert>
- 多个参数用
@Param
void updateUser(@Param("id") String id, @Param("us") User user);
<update id="updateUser">
update users
set username = #{us.username},
email = #{us.email}
where id = #{id}
</update>
最佳实践:为了统一化取参,即使一个参数也使用@Param
返回值处理
返回普通数据 resultType
- 返回基本类型、String、Long、普通javeBean都只需要在
resultType中声明返回值的全限定类名 - mybatis.configuration.map-underscore-to-camel-case=true
开启驼峰映射:表中查询结果集中a_column列会自动被映射为bean中的aColumn属性
自定义映射结果集 resultMap
当表中结果和javabean属性不能映射(字段名不对应,即使开启驼峰映射也不行),这时需要使用自定义映射
<!-- id自定义的结果映射唯一名 type-接受结果bean的全类名 -->
<resultMap id="UserRm" type="org.example.mybatis.entity.User">
<!-- id标签-主键 result标签-其他普通列 column-结果表的列名 property-bean的属性名 -->
<id column="id" property="id"/>
<result column="user_phone" property="phone"/>
</resultMap>
<select id="getUserByIdRm" resultMap="UserRm">
select * from users;
</select>
一对一,当遇到某个属性的类型是另一个javaBean,resultMap里面需使用association。
@Data
public class Order {
private String id;
private String productName;
private User user;
}
Order getOrderWithUserById(@Param("id") String id);
<resultMap id="OrderRm" type="org.example.mybatis.entity.Order">
<id column="id" property="id"/>
<result column="product_name" property="productName"/>
<!-- 一对一,当遇到某个属性类是另一个javabean,需使用association。-->
<association property="user" javaType="org.example.mybatis.entity.User">
<id column="user_id" property="id"/>
<result column="user_phone" property="phone"/>
<result column="username" property="username"/>
<result column="email" property="email"/>
</association>
</resultMap>
<select id="getOrderWithUserById" resultMap="OrderRm">
select orders.*, username, email, user_phone from orders left join users on orders.user_id = users.id
where orders.id = #{id}
</select>
一对多,当遇到某个属性的类型是另一个javaBean的集合,resultMap里面需使用collection。
@Data
public class User {
private Integer id;
private String username;
private String email;
private Date createdAt;
private String phone;
private List<Order> orderList;
public User(String username, String email) {
this.username = username;
this.email = email;
}
}
User getUserAllOrders(String id);
<resultMap id="getUserAllOrdersRm" type="org.example.mybatis.entity.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="email" property="email"/>
<result column="user_phone" property="phone"/>
<collection property="orderList" ofType="org.example.mybatis.entity.Order">
<id column="orderId" property="id"/>
<result column="product_name" property="productName"/>
</collection>
</resultMap>
<select id="getUserAllOrders" resultMap="getUserAllOrdersRm">
select users.*, orders.product_name, orders.id orderId
from users
left join orders on users.id = orders.user_id
where users.id = #{id}; </select>