有一个代码的设计问题,大佬们帮帮我

146 天前
 tongjiann

简单介绍一下情况。

  1. 我们是用的是 jdk8+mybatis+MybatisPlus+diboot(小众的 MP 的增强,没看见过可忽略)的后端项目
  2. 每个业务表中都有一个 period(会计期间)字段

现在有一个 PM 提了一个很容易理解但是很傻逼的 Feature:

只有管理员开放指定 period 之后,才能对指定 period 的业务表数据进行增删改查(增删改已经做限制,采用下面第二种方法。),否则都不允许(返回空或提示权限不足) 管理员无视上面一条要求

初步想法

  1. 在所有的查询语句执行前在代码层添加可查询的 period 列表。
    • 比如 select * from table a where id = 'xxx',那就改成 select * from table a where id = 'xxx' and period in (valid_period_list);
  2. 对所有的查询出来的数据进行校验。由于增删改单次进行的对象的数据量较小,所以在增删改操作进行前做一次查询取出所有被查询的数据并判断 period ,这样损耗较小,目前可以接受。但是当查询的时候使用系统方法我认为会严重损耗性能。
    • 比如 select * from table a where id = 'xxx'。在查询出数据之后,在代码层进行一次校验,判断 period 是否合理。

请问一下大佬们对这个 Feature 有什么比较好的实现经验吗,或者说比较好的 idea

5017 次点击
所在节点    程序员
43 条回复
iMoutai
146 天前
MyBatis-Plus 自带的数据权限插件不符合要求吗?
m1ch3ng
145 天前
@andy2415 #19 试了下,oracle 分页遇到了一个问题,sql 打印:

==> Preparing: SELECT * FROM (SELECT TMP.*, ROWNUM ROW_ID FROM (SELECT id, serial_number, command, sap_no, product_no, voucher_id, voucher_detail_id, voucher_details_id, record_status, remark, created_time, updated_time, pro_factory, batch_no, product_date, expire_date, product_num, pro_unit_cost, rx_flag, operator_name, operate_date, total_amount, price, old_voucher_id, old_voucher_details_id, spp_hsbl, settlement_time FROM POS_INVENTORY_UPLOAD_RECORD WHERE (command = ?)) TMP WHERE ROWNUM <= ?) WHERE ROW_ID > ? AND created_time >= {d '2024-07-26'}
==> Parameters: SALE_OR_REFUND_SALE(String), 4(Long), 2(Long)
<== Total: 0

其中 created_time >= {d '2024-07-26'} 是我自定义拦截器加的 GreaterThanEquals ,然而 mybatis-plus 在 oracle 场景下把它放在了最外层查询里面,如果想要实现放在 WHERE (command = ? AND created_time >= {d '2024-07-26'}),请问该如何调整?

P.S. 我配置的自定义拦截器顺序是放在分页插件后面的
m1ch3ng
145 天前
自己研究了下解决了,代码如下:
@Override
protected void processSelect(Select select, int index, String sql, Object obj) {
// 默认情况下,直接加到最外层查询的 where 后面
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
if (select.toString().contains("ROWNUM")) {
// oracle 分页的情况,需要找到最内层的查询,然后加到 where 后面
plainSelect = getInnerSelect(plainSelect);
}
// 给查询添加条件
GreaterThanEquals greaterThanEquals = getGreaterThanEquals();
Expression where = plainSelect.getWhere();
plainSelect.setWhere(where == null ? greaterThanEquals : new AndExpression(where, greaterThanEquals));
}

private static PlainSelect getInnerSelect(PlainSelect select) {
if (select.getFromItem() instanceof SubSelect) {
PlainSelect fromSelect = (PlainSelect) ((SubSelect) select.getFromItem()).getSelectBody();
return getInnerSelect(fromSelect);
}
return select;
}

@NotNull
private static GreaterThanEquals getGreaterThanEquals() {
GreaterThanEquals greaterThanEquals = new GreaterThanEquals();
greaterThanEquals.setLeftExpression(new Column("created_time"));
greaterThanEquals.setRightExpression(new DateValue("'2024-07-26'"));
return greaterThanEquals;
}

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1060204

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX