在SpringBoot开发过程中,我们使用 ***Mapper.xml
+***Mapper.java
来封装对数据库表的 CURD
操作,正常每张表会有一组对应的文件。
一、Mapper常见用法
下面例举一个查询操作:
- 数据表
t_sap_customer
,表中有字段id、code、name、create_time、update_time、last_ver、is_valid
- 现在需要根据
id
、is_valid
来查询一条数据
TSapCustomerMapper.java 代码:
package com.starcharge.repository.db1.product.mapper;
import com.starcharge.repository.db1.product.domain.TSapCustomerDO;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Repository
public interface TSapCustomerMapper {
TSapCustomerDO detail(String id,String isValid);
}
TSapCustomerMapper.xml 代码:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.abc.repository.db1.product.mapper.TSapCustomerMapper">
<!-- 创建数据库与实体类字段对应关系 -->
<resultMap id="BaseResultMap" type="com.abc.repository.db1.product.domain.TSapCustomerDO">
<result property="id" column="id"/>
<result property="name" column="name" jdbcType="VARCHAR"/>
<result property="createTime" column="create_time" jdbcType="VARCHAR"/>
<result property="updateTime" column="update_time" jdbcType="VARCHAR"/>
<result property="lastVer" column="last_ver" jdbcType="VARCHAR"/>
<result property="isValid" column="is_valid" jdbcType="VARCHAR"/>
</resultMap>
<!--查询列表-->
<select id="detail" resultMap="BaseResultMap">
select
id,code,name,last_ver,is_valid,create_time,update_time
from t_sap_customer
where is_valid = #{isValid} and id = #{id}
</select>
</mapper>
上面TSapCustomerMapper.java
和TSapCustomerMapper.xml
就是一组针对数据库表t_sap_customer
的实体类操作,*Mapper.java
负责定义实体类的对外Api,*Mapper.xml
负责实现具体的CURD
操作的SQL语句。
两者使用xml文件中的id
属性值来做映射对应,具体来说就是TSapCustomerMapper
接口中的detail
方法,会到xml
文件中找到对应的id='detail'
来执行。
二、mapper.xml入参方法
这里常见的一个问题是,我们在执行SQL
的时候会有各种入参,那么我们要如何将api
中的入参传入xml
文件中,请看下面介绍。
1、简单传参
TSapCustomerMapper.java
和TSapCustomerMapper.xml
之间,默认按照参数名入参。
以下的入参都是可以正常运行的:
//TSapCustomerMapper.java
@Repository
public interface TSapCustomerMapper {
TSapCustomerDO detail(String id, String isValid);
}
//TSapCustomerMapper.xml
<select id="detail" resultMap="BaseResultMap">
select
id,code,name,last_ver,is_valid,create_time,update_time
from t_sap_customer
where is_valid = #{isValid} and id = #{id}
</select>
2、@Param传参
//TSapCustomerMapper.java
@Repository
public interface TSapCustomerMapper {
TSapCustomerDO detail(@Param("id1") String id, @Param("isValid1") String isValid);
}
//TSapCustomerMapper.xml
<select id="detail" resultMap="BaseResultMap">
select
id,code,name,last_ver,is_valid,create_time,update_time
from t_sap_customer
where is_valid = #{isValid1} and id = #{id1}
</select>
3、Map入参
//SapCustomerImpl.java
@Service
public class SapCustomerImpl implements SapCustomerService {
@Override
public TSapCustomerDO detail(String id) {
HashMap<String,String> map=new HashMap<String,String>();
map.put("id",id);
map.put("isValid","2");
TSapCustomerDO r = sapCustomerMapper.detail(map);
return r;
}
}
//TSapCustomerMapper.java
@Repository
public interface TSapCustomerMapper {
TSapCustomerDO detail(HashMap query);
}
//TSapCustomerMapper.xml
<select id="detail" resultMap="BaseResultMap">
select
id,code,name,last_ver,is_valid,create_time,update_time
from t_sap_customer
where is_valid = #{isValid} and id = #{id}
</select>
4、param、arg入参
xml文件中默认会传入arg0...argN
、param1...paramN
两个使用索引的入参。arg
从0开始,param
从1开始。
//TSapCustomerMapper.java
@Repository
public interface TSapCustomerMapper {
TSapCustomerDO detail(String id, String isValid);
}
//TSapCustomerMapper.xml
<select id="detail" resultMap="BaseResultMap">
select
id,code,name,last_ver,is_valid,create_time,update_time
from t_sap_customer
where is_valid = #{param2} and id = #{param1}
</select>
5、简单入参+Map入参
//SapCustomerImpl.java
@Service
public class SapCustomerImpl implements SapCustomerService {
@Override
public TSapCustomerDO detail(String id) {
HashMap<String,String> map=new HashMap<String,String>();
map.put("isValid","2");
TSapCustomerDO r = sapCustomerMapper.detail(id, map);
return r;
}
}
//TSapCustomerMapper.java
@Repository
public interface TSapCustomerMapper {
TSapCustomerDO detail(String id, HashMap map);
}
//TSapCustomerMapper.xml
<select id="detail" resultMap="BaseResultMap">
select
id,code,name,last_ver,is_valid,create_time,update_time
from t_sap_customer
where is_valid = #{map.isValid} and id = #{id}
</select>
三、#{} 和 ${} 的区别
MyBatis中 #{ }和${ }都可以用来动态传递参数。
1、不同点
#{}
对应底层使用 jdbc
的PreparedStatementd
对象来执行sql语句,在SQL中相当于一个参数占位符“?”,用来补全预编译语句。它补全预编译语句时,可以理解为在此参数值两端统统使用单引号引起来。 #{}
里除了可以写接收参数的名称外,还可以设置javaType
,jdbcType
,mode
等。
${}
对应底层使用 jdbc
的Statement
对象来执行sql
语句,就是单纯的字符串拼接,拼接完成后才会对SQL
进行编译、执行,所以性能较低,也无法复用。但是在有些 #{ }
无法胜任的地方,还是会需要${ }
来完成。
2、结论
#{}
很大程度防止sql
注入,提高系统安全,一般能用#
的地方就别用$
。
${}
无法防止Sql
注入,如果写的SQL
语句的参数内容应该作为SQL
的一部分,此时必须使用$
,比如:表名称,order by
排序字段,分组 group by
等。