Mybatis分表数据汇总的一种思路

前言

作者在使用Mybatis+Spring Boot框架的时候,遇到了一个需求,就是定期汇总3个用户分表中的数据去重后进行后期处理,实现思路比较简单,但是有一些需要注意的地方。

相关sql

作者对sql语言仅有一定的基础,所以提出的方案未必最优,但是可以解决当前的问题。

对于3个用户表user,user1和user2,可以这样写——

select * from user union select * from user1 union select * from user2

union 和union all的区别

最大的区别就是union对于并集同时完成了去重的操作,相当于使用了distinct,而union all只取并集,不进行任何其他操作。

结合Spring Boot框架

松耦合配置

作者使用了Spring Boot框架,故可以通过配置文件和@ConfigurationProperties注解方便地将所有的表名注入到一个String类型的List中,以供下一步使用。

其中prefix属性表示类中的所有属性都来自于application.yml/application.properties中的sql,如tableList就对应sql.tableList=XXX。

使用foreach标签完成需求

作为Mybatis中最为强大的标签之一的foreach标签,它可以灵活地完成各种批量、循环相关的数据库需求。

Mybatis foreach标签的使用

我们观察上面的sql语句,发现联合查询中共同的是select * from和union,不同的是表名。结合foreach标签的各个属性我们可以这么做。

<select id="selectAllCrossTable" useCache="false" flushCache="false" resultType="com.school.springboot.entity.User">
        select * from user union all
    <foreach collection="list" item="table" separator="union">
        select * from ${table}
    </foreach>
</select>

将表名通过${table}注入,使用union作为不同select语句的分隔符,最终就可以得到这样的sql语句

select * from user union select * from user1 union select * from user2

Mapper层

@Mapper
public interface UserMapper extends BaseMapper<User> {

    List<User> selectAllCrossTable(List<String> list);
    
}

Service层

@Service(value = "userService")
@SuppressWarnings("all")
@Transactional(rollbackFor = Exception.class, isolation = Isolation.DEFAULT)
@RequiredArgsConstructor
@ConfigurationProperties(prefix = "sql")
@Data
public class UserService {

    private List<String> tableList;

    private final UserMapper userMapper;

    private final RedisTemplate firstRedisTemplate;

    //...其他的业务逻辑代码

    public List<User> selectAllCrossTable() {
        return userMapper.selectAllCrossTable(tableList);
    }

}

Controller层

@Slf4j
@RestController
@SuppressWarnings("all")
@RequestMapping(value = "/user")
@CrossOrigin
public class UserController {

    @Autowired
    private UserService userService;

    // @RequiresGuest
    @ResponseBody
    @RequestMapping(value = "/crossTable", method = RequestMethod.GET)
    public Result getAllCrossTable() {
        return Result.success(userService.selectAllCrossTable());
    }
}

Postman测试

使用postman进行测试,接口功能正确

注意事项

#和$的区别

我们使用Mybatis框架时,用的最多的应该是#{}这样的形式注入参数,但是这里传入的是字符串,如果仍然使用#{}的形式,那么得到的sql语句中表名会带有单引号,这样的sql语句无法执行,所以必须换成${table}的形式,它可以直接将字符串注入,但是安全性较差,在其他场景不推荐使用。

如何定期汇总数据?

这个就仁者见仁智者见智了,不过目前Spring Boot使用的主流定时调度框架估计只有Quartz了。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值