mybatis

30 阅读2分钟

准备工作

  • 相关maven依赖 Lombok Spring Web MyBatis Framework MySQL 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>
  • 一对一,当遇到某个属性的类型是另一个javaBeanresultMap里面需使用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>