Git Product home page Git Product logo

jointqueryupdater's Introduction

joint-query-updater

「联查直更」项目前端

后端地址:https://github.com/Huaguang-XinZhe/JointQueryUpdaterBackend?tab=readme-ov-file

简介

image-20240227100444592

这是一个非常简单的 “项目”(或许算不上项目),前端用 Vue2 + 原始的前端三件套构建(用了少许的 Element UI),后端用 Spring Boot + MyBatis 构建。目前已经部署上线,可通过此域名❓访问。

背景

为什么我要做这个 “项目” ?

我有一个记录的习惯,平时会不自觉的收集一些想法、疑问、待办、需求等等,这些东西都在同一个入口(Typora)进行记录,日渐累积。

image-20240227103410043

等到终于有空了,我对这些记录进行整理,集中打标,然后通过程序扫描,分列,入库。这样方便我通过 SQL 语句进行查询分析,也能快速、批量修改一些数据。

根据记录数据的结构,我创建了以下两张表:

-- 创建一张输入表(主表)
create table myinput(
    id int primary key auto_increment,
    content text not null -- TEXT 类型理论上可以存储 65535 个字符的数据(实际会小于这个数),够用了
);

-- 创建一张标签表
create table mytag(
    id int primary key auto_increment,
    input_id int not null,
    c1 varchar(20) not null,
    c2 varchar(50),
    c3 varchar(50),

    foreign key (input_id) references myinput(id) -- 外键在多的一方
);

呈现如下结构:

image-20240227103615540

image-20240227103700647

很好,现在就可以自由分析、修改了。

我执行了这条联查 SQL:

select i.content, t.c1, t.c2
from myinput i
left join mytag t on i.id = t.input_id
where t.c1 = '待办';

但当我试图修改时,却提示说结果是只读的:

image-20240227105502298

在 GPT 的帮助下,我在以上 SQL 的上方加了一句,创建了一个视图:

create view v_c1 as

这次允许修改了,但提交后还是报错了:

image-20240227110221556

仔细查看其更新 SQL:

ling_guang> UPDATE ling_guang.v_c1 t SET t.c1 = 'Typora' WHERE t.content LIKE '在暗黑模式下需要修改一下滚动条的颜色,增强对比度。' ESCAPE '#' AND t.c1 LIKE '待办' ESCAPE '#' AND t.c2 LIKE 'Typora 样式' ESCAPE '#'

t 表(mytag 表)中是没有 content 字段的,t.content 不管怎样模糊匹配,都找不到对应的可更新条目。

我又反复测试了几次,也试了试单表查询,发现单表查询的结果是可以修改的,对单表查询创建的视图也是,而多表联查就不行!

那怎么办呢?我只能通过联查才能在看到内容的同时看到其标签呀,而且我是有可能对数据进行修改的。

如果我能自己掌控更新语句就好了,这样我就能根据修改的位置判断它要更新那张表的哪个字段、哪一行了。

“哪个字段” 好办,“哪一行” 的话,就还需要一点数据。

我得把两张表的 id 在联查的时候暴露出来,这样就能知道是哪一行了。

于是,我创建了这样的视图:

create view v_c2 as
select i.id as myinput_id, t.id as mytag_id, i.content, t.c1, t.c2
from myinput i
left join mytag t on i.id = t.input_id
where t.c1 = '待办';

但结果依然不理想:

image-20240227113655584

DataGrip 的更新语句让我觉得有点 “傻”,我都给了更新位置所在行的 id 了,它判断一下更新的是哪张表,然后选择那张表的 id 去定点更新不就行了,为啥老是要用模糊匹配呢?

随后,我让 GPT 帮我找找有没有能满足我需求的插件或工具啥的,但没找到,这符合我的预期,毕竟这个需求太小、太细了。

看来,我只能自己造了。

彼时我正在学习 Vue2,也正好有这个能力,那就干吧。

使用

我管这个 “应用” 叫「联查直更」,取 “能在多表联查的结果上直接修改更新” 之意。目前该功能确已实现。

用的时候,只需要将联查 SQL 复制粘贴到输入框中,然后点击确定或按下 Ctrl + Enter,即可将该 SQL 语句发至服务器远程执行,并返回数据,过滤无关列(默认)后展示。

然后便可在查询结果上直接修改了,修改过的单元格会高亮显示,全部修改完成后可点击 “全部提交”(仿 DataGrip 设计),而后程序会根据所有修改的位置自动生成相应的更新语句,完成更新并返回结果。

image-20240227163226312

原理

每一个修改单元格都是一个更新对象,多个更新对象形成一个列表,一同发送到服务器。

@Data
public class UpdateObj {
//    String originalValue;
    @JsonProperty("changedValue")
    String value;
    @JsonProperty("fieldName")
    String column;
    @JsonProperty("rowId")
    int id;
    @JsonProperty("tableName")
    String table;
}

为优化性能,同一张表同一行的不同列将会放在一起更新:

// 对 updateObjs 进行分组
Map<UpdateKey, Map<String, Object>> groupedUpdates = new HashMap<>();

for (UpdateObj updateObj : updateObjs) {
    UpdateKey key = new UpdateKey(updateObj.getTable(), updateObj.getId());
    // computeIfAbsent() 方法的作用是:如果 key 不存在,则创建一个新的 value,否则返回已存在的 value
    groupedUpdates.computeIfAbsent(key, k -> new HashMap<>())
            .put(updateObj.getColumn(), updateObj.getValue());
}
System.out.println("groupedUpdates = " + groupedUpdates);

而 MyBatis 负责动态生成更新语句:

<!-- 这里的 column 代表 updates(Map) 中的键,而 value 代表其中的值 -->
<update id="updateTable">
    UPDATE ${table}
    SET
    <foreach item="value" index="column" collection="updates" separator=",">
        ${column} = #{value}
    </foreach>
    WHERE id = #{id}
</update>

回顾

这个 “项目” 我花了近一周时间,核心功能已经实现,但还有一些已测试的交互没能应用。

因为我突然发现自己的需求有点简单,稍微忍一忍(交互),把自己的核心诉求解决后好像就没它什么事儿了,感觉再做下去意义不大。

也确实,它并不是必须的,把两个表合为一个表,这不就避免了 “在多表联查结果上直接修改” 的问题了吗?当时怎么没想到呢?还是前期准备工作做的不够,轻易投入了!

颇有点后悔,毕竟又是一个星期。不过,一想到这是对 Vue2 的一次顶好的实践,心情就好多了,我并没有失去太多。

发展

这个 “项目” 还可以继续发展,至少可以把目前写死的部分(表数据)盘活来,可以加上一点 SQL 注入的安全性检测。

这样下次遇到类似情境的时候就可以快速上手,而无需手动修改数据源和表头相关代码了。

有时间的时候再做吧。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.