1.通过注解@Select
mapper类
// 此处maper注解最好和配置文件中的 mapper-locations: com.wlw.mapper配合使用
@Repository
@Mapper
public interface RecDescribeMapper {
/* 不加@param注解会报错
* @param注解必须加上,否则mybatis就会使用默认注解(param1、param2、按顺序...),
* 这时可以把@select 中的sql语句的#{bf}要改为#{param0},#{ef}要改为#{param1}。
* 如果不改就会报错:如图1-1所示
* 所以建议参数都加@Param注解
@Select({"select * from RecDescribe where TimeFlag >= #{bF} and TimeFlag <= #{eF}"})
public List<RecDescribe> selectByTimeFlag(@Param("bF") String bF, @Param("eF") String eF);
}
调用类
/**
* 查询gp数据类
* @author Thomas
*/
@Service
public class QueryServiceImpl implements QueryService {
@Autowired
RecDescribeMapper recDescribeMapper;
public List<GPS> queryPeriodData(String moduleName, String bTime, String eTime) {
String bf = bTime.split(" ")[1].replace("-", "");
String ef = eTime.split(" ")[1].replace("-", "");
List<RecDescribe> recs = recDescribeMapper.selectByTimeFlag(bf, ef);
System.out.println(recs);
}
}
2通过注解 @SelectProvider
SelectProvider类
多个方法参数时,用Map进行代替,否则会找不到对应的参数并报错
org.apache.ibatis.binding.BindingException:
Parameter 'arg0' not found. Available parameters are [param5, bTime, param6, eTime, moduleTable, kid, gpsTable, model, param3, param4, param1, param2]
at org.apache.ibatis.binding.MapperMethod$ParamMap.get(MapperMethod.java:202) ~[mybatis-3.4.2.jar:3.4.2]
at org.apache.ibatis.builder.annotation.ProviderSqlSource.extractProviderMethodArguments(ProviderSqlSource.java:111) ~[mybatis-3.4.2.jar:3.4.2]
at org.apache.ibatis.builder.annotation.ProviderSqlSource.createSqlSource(ProviderSqlSource.java:89) ~[mybatis-3.4.2.jar:3.4.2]
at org.apache.ibatis.builder.annotation.ProviderSqlSource.getBoundSql(ProviderSqlSource.java:73) ~[mybatis-3.4.2.jar:3.4.2]
其中 param0 ~ param5 (有时会出现 arg0 ~ arrg5) 是mybatis的默认参数,对应本例Mapper类中
public List<GPS> queryGpsDataByPeriod(@Param("gpsTable") String gpsTable,
@Param("moduleTable") String moduleTable,
@Param("kid") String kid,
@Param("model")String model,
@Param("bTime")String bTime,
@Param("eTime")String eTime);
方法的参数(按顺序对应)
其他的bTime、eTime等,是因为我加了@Param注解才产生的,如果不加,就没有这些项。
/**
* 动态生成sql语句
* 方式1相比于方式2 可以生成动态表名,但是不会进行预编译过程,可能产生sql注入
* @author Tomas
* @date 2017/12/13
*/
public class DynamicSqlProvider {
/**
* 方式1
* @param map
* @return
*/
public String findGpsPeriodDataBySql1(Map<String, String> map){
/*map中是参数名称和值得key-value对
* 如果Mapper中加了@Param 注解就可以用参数名作为map的key
* 时间是无论Mapper接口的方法中加不加@Param注解,都可以用mybatis默认的参数名称(param0 ~ param5)(arg0 ~ arrg5)获取参数值
*/
// 通过参数名称获取对应值
// String GpsTable = map.get("gpsTable");
// String moduleTable = map.get("moduleTable");
// String kid = map.get("kid");
// String model = map.get("model");
// String bTime = map.get("bTime").substring(1);
// String eTime = map.get("eTime").substring(1);
// 此处用param
String GpsTable = map.get("param0");
String moduleTable = map.get("param1");
String kid = map.get("param2");
String model = map.get("param3");
String bTime = map.get("param4").substring(1);
String eTime = map.get("param5").substring(1);
// 打印map 可以发现map中已经含有bTime 、param0 ~param5的参数K-V对
// {param5= 2015-12-02 15:01:42, bTime= 2015-12-02 15:01:42, param6= 2017-12-14 15:01:42, eTime= 2017-12-14 15:01:42, moduleTable=LTM20161124, kid=f01f35d5-24b1-48ad-9246-9c3b7267184b, gpsTable=GPS20161124, model=4G, param3=f01f35d5-24b1-48ad-9246-9c3b7267184b, param4=4G, param1=GPS20161124, param2=LTM20161124}
System.out.println(map.toString());
return "Select g.*,m.KID,m.LAC,m.CI,m.GpsTime,'"+ model +"' Model" +
" from "+ GpsTable +" g left join " + moduleTable +" m " +
" on g.GpsTime = m.GpsTime where" +
" m.KID = '"+ kid +"' and m.GpsTime > '"+ bTime +"' and m.GpsTime < '"+ eTime +"'";
}
/**
* 方式2
* 通过#{key}直接获取map中对应的参数名称,前提是Mapper中加@Param注解
* 推荐此方式
* @param map
* @return
*/
public String findGpsPeriodDataBySql(Map<String, String> map){
return new SQL(){
{
SELECT("g.*,m.KID,m.LAC,m.CI,m.GpsTime,#{model} Model ");
FROM("GPS20161124 g ");
INNER_JOIN("MM20161124 m on g.GpsTime = m.GpsTime ");
WHERE("m.KID = #{kid} and m.GpsTime > #{bTime} and m.GpsTime < #{eTime}");
}
}.toString();
}
}
Mapper类
/**
* 不使用@param注解
* SelectProvider中对应方法的参数 不能 通过名称直接获,只能按参数排序获取 #{param0}
* @param GpsTable
* @param moduleTable
* @param kid
* @param model
* @param bTime
* @param eTime
* @return
*/
@SelectProvider(type = DynamicSqlProvider.class,
method = "findGpsPeriodDataBySql")
public List<GPS> queryGpsDataByPeriodO(String GpsTable, String moduleTable, String kid, String model, String bTime, String eTime);
/**
* 使用字段名
* SelectProvider中对应方法的参数 可以 通过名称直接获取(对应方式2中的 #{})
* @param gpsTable
* @param moduleTable
* @param kid
* @param model
* @param bTime
* @param eTime
* @return
*/
@SelectProvider(type = DynamicSqlProvider.class,
method = "findGpsPeriodDataBySql")
public List<GPS> queryGpsDataByPeriod(@Param("gpsTable") String gpsTable,
@Param("moduleTable") String moduleTable,
@Param("kid") String kid,
@Param("model")String model,
@Param("bTime")String bTime,
@Param("eTime")String eTime);
调用类 和 1 中的调用类相似。
3. #和$的区别
#{}
1.#能防止sql注入,$不能
2.$方式一般用于传入数据库对象,例如传入表名.
3.MyBatis排序时使用order by 动态参数时需要注意,用$而不是#
4.#传入值是引用,而$是其本身:
id = 1, select #{id} from tablename -> select 1 from tablename(引用)
id = 1, select ${id} from tablename -> select id from tablename