CRUD简述
写业务代码我们免不了会一直围绕着CRUD转,这是基础,也是根本,把CRUD做好了也是一件不简单的事情,让我们扎扎实实地去做好这件事。
插入
批量插入:
insert into test_table
(`name`,`age`)
values
<foreach collection="list" item="item" separator=",">
(
#{item.name},
#{item.age}
)
</foreach>
注意:如果dao层传入的集合参数使用了@Param(value=“xxxList”),则语法要调整:
insert into test_table
(`name`,`age`)
values
<foreach collection="xxxList" item="item" separator=",">
(
#{item.name},
#{item.age}
)
</foreach>
批量插入更新
假设name是唯一主键,插入时可能会存在冲突
insert into test_table
(`name`,`age`)
values
<foreach collection="xxxList" item="item" separator=",">
(
#{item.name},
#{item.age}
)
</foreach>
ON DUPLICATE KEY UPDATE age=values(age)
foreach各参数说明:
1.collection:映射Mpper接口方法参数的集合名称,如果Mapper接口方法参数使用了@Param(value=“xxx”)指定了名称,则这里使用xxx,反之则使用默认值”list”
2.item:集合中单个元素的别名
3.index:迭代次数,从0开始
4.open:循环sql开始符号
5.close:循环sql结束符号
6.separator:每次迭次之间的分隔符
查询
模糊查询
- 如果传入的模糊字段是字符串,建议先进行trim()
- 如果数据库有相关字段且建立了索引,可以在数据库层使用like进行模糊查询,注意mybatis like用法-LIKE CONCAT(’%’,#{searchItem},’%’)
- 如果有些字段数据库中没有,则可以通过代码来实现,使用排除法,如果需求场景是这样:前端传入的一个模糊字段匹配多个后端字段,伪代码如下:
List<T> result = new ArrayList();
if(fuzzyItem != null) {
// 匹配字段item1
if(item1.contains(fuzzyItem)) {
// 满足要求,对应的对象数据加入返回结果中
result.add(item1);
continue;
}
// 匹配字段item2
if(item2.contains(fuzzyItem)) {
// 满足要求,对应的对象数据加入返回结果中
result.add(item2);
continue;
}
// 没有命中,则继续下一轮遍历
continue;
}
分页查询
- 使用github分页器,PageHelper.startPage(pageNum, pageSize);
- 如果是对外部接口返回的全量数据进行分页,可以参考如下方法:
public static <T> List<T> readByPage(List<T> srcList, int pageNum, int pageSize) {
if (CollectionUtils.isEmpty(srcList)) {
return new ArrayList<>();
}
int fromIndex = pageNum > 0 ? (pageNum - 1) * pageSize : 0;
int toIndex = pageNum * pageSize;
int size = srcList.size();
if (size <= fromIndex) {
return new ArrayList<>();
} else if (size > fromIndex && size < toIndex) {
return srcList.subList(fromIndex, size);
} else {
return srcList.subList(fromIndex, toIndex);
}
}
- 如果是接口做了查询数量限制,比如:一次查询100的用户id对应的用户数据,可以参考如下方法:
public static <T, R> List<R> readByPage(List<T> params, int limit, Function<List<T>, List<R>> readFunction) {
if (CollectionUtils.isEmpty(params)) {
return new ArrayList<>();
}
if (params.size() <= limit) {
return readFunction.apply(params);
} else {
// 不能用subList,会报并发修改异常
List<T> tmpParams = new ArrayList<>();
for (int i = 0; i < limit; i++) {
tmpParams.add(params.get(i));
}
List<R> totalResult = readFunction.apply(tmpParams);
int total = params.size();
List<T> leftParams = new ArrayList<>();
// for循环去填充参数,当limit较小,总的size较大时,会比较耗性能
for (int i = limit; i < total; i++) {
leftParams.add(params.get(i));
}
List<R> tmpResult = readByPage(leftParams, limit, readFunction);
if (totalResult != null && tmpResult != null) {
totalResult.addAll(tmpResult);
}
return totalResult;
}
}
多字段排序
- 使用数据order by实现多字段排序:oder by filed1 desc, filed2 desc
- 使用流排序:stream().sorted(Comparator.comparing(Function1).thenComparing(Function2).thenComparing(Function3))
- 使用集合工具排序:
Collections.sort(srcList,Comparator.comparing().thenComparing().thenComparing())
修改
批量修改
- 使用mybatis-foreach语法组装sql,注意这种方式需要在mysql连接配置中加:&allowMultiQueries=true属性
<foreach collection="list" item="item" index="index" open="" close="" separator=";">
update test_table
<set>
<if test="item.name != null">
clazz_id = #{item.name,jdbcType=VARCHAR},
</if>
<if test="item.age != null">
teacher_id = #{item.age,jdbcType=BIGINT},
</if>
</set>
where id = #{item.id,jdbcType=BIGINT}
</foreach>
“allowMultiQueries=true”的作用:
1.可以在sql语句后携带分号,实现多语句执行。
2.可以执行批处理,同时发出多个SQL语句
多字段修改
- 修改单条记录多字段注意不能使用and连接符合,and符号在这里是逻辑与操作
删除
- 业务相关的数据尽量使用逻辑删除
- 删除操作尽量要做权限验证,表设计中要设计operator_id、create_date、update_date,记录操作者、创建时间、更新时间