返回介绍

9.4 分表

发布于 2025-04-26 13:08:35 字数 2490 浏览 0 评论 0 收藏

在大型互联网中应用表的数据会很多,为了减少单表的压力,提高性能,我们往往会考虑分表的算法。

在实际工作中,比如大型公司的账单表(t_bill)可能有上亿条,对于这种情况我们往往需要进行分表处理。账单表有许多数据,我们可以把 2015 年的账单保存在表(t_bill_2015)中,2016 年的账单保存在表(t_bill_2016)中,未来我们还需要建 2020 年的表(t_bill_2020)。MyBatis 允许我们把表名作为参数传递到 SQL 中,这样就能迅速解决这些问题了。

假设有一个场景,用户希望知道年份和账单编号(id)以查找账单,那么我们可以知道两个参数,即年份和 id。其中年份对账单表的名称产生影响,id 则是我们查询的参数。让我们先定义接口参数,如代码清单 9-21 所示。

代码清单 9-21:使用年份作为表名参数

public Bill getBill(@Param("year") int year,@Param("id") Long id);

很普通的定义,然后我们看看映射器 XML 的定义代码,如代码清单 9-22 所示。

代码清单 9-22:表名也是参数

<select id="getBill" resultType="com.learn.chapter9.pojo.Bill">
        select id, bill_name as billName, note 
        from t_bill_${year} where id = #{id}
</select>

${year}的含义是直接让参数加入到 SQL 中。换句话说,我们可以使用这样的一个规则:让 SQL 的任何部分都可以被参数改写,包括列名,以此来满足不同的需求。但是这样是危险的,比如把 year 参数修改为 1900,那么这条语句的 SQL 就变为了查询 t_bill_1900,而这个表根本就不存在,这会导致发生错误。如果不是很有必要,笔者不推荐使用。对于参数笔者还是建议使用 #{} 的形式。让我们测试代码清单 9-23。

代码清单 9-23:测试分表表名参数

SqlSession session = SqlSessionFactoryUtil.openSqlSession();
        try {
            BillMapper billMapper = session.getMapper(BillMapper.class);
            Bill bill2015 = billMapper.getBill(2015, 1L);
            System.err.println(bill2015.getBillName());
            Bill bill2020 = billMapper.getBill(2020, 1L);
            System.err.println(bill2020.getBillName());
        } catch(Exception ex) {
            session.rollback();
            ex.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }

运行一下,得到下面的结果。

DEBUG 2015-12-21 14:31:39,310 org.apache.ibatis.logging.LogFactory: Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
  ......
  DEBUG 2015-12-21 14:31:39,713 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==>  select id, bill_name as billName, note from t_bill_2015 where id = ?
  DEBUG 2015-12-21 14:31:39,742 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==> Parameters: 1(Long)
  DEBUG 2015-12-21 14:31:39,763 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: <==      Total: 1
bill_name_2015
  DEBUG 2015-12-21 14:31:39,765 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==>  Preparing: select id, bill_name as billName, note from t_bill_2020 where id = ?
 ......
  DEBUG 2015-12-21 14:31:39,771 org.apache.ibatis.datasource.pooled.Pooled DataSource: Returned connection 527446182 to pool.

从日志我们可以看出表名参数传递完全成功。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。