【问题标题】:Compare two big strings without storing them in database比较两个大字符串而不将它们存储在数据库中
【发布时间】:2020-06-08 11:35:56
【问题描述】:

我想检测用户是否修改了之前的值中的某些数据。此数据存储在不同数据库表的多个字段中。

假设第一次运行的数据是:

“罗杰·费德勒”、“法拉利”、“键盘”、“罗密欧”

在第二次运行时:

“罗杰·费德勒”、“法拉利”、“键盘”、“朱丽叶”

我需要比较第二次运行的数据是否被修改。为此,我创建了一个键,其中存储了所有字段的连接。这将导致这样的事情: 'RogerFedererFerrariKeyboardRomeo' 用于第一个,'RogerFedererFerrariKeyboardJuliet' 用于第二个。然后我将比较这些键。这种方法的问题是我有超过 50 个字段,并且键会很大,这会影响我的数据库。

由于我不关心实际数据值,只想查看数据是否被修改,我可以为我的数据创建 POJO/JSON 并将 CRC32/MD5 校验和计算为键并进行比较吗?这种方法会出现什么问题?有没有更好的替代方案?

【问题讨论】:

  • 是的,您可以使用校验和。
  • 哪种校验和最好(高效)?哪种对象类型更有效:POJO、XML 还是 JSON?
  • 如何存储每行的哈希?
  • 您可以使用 CRC32/MD5 但也可以检查冲突

标签: java string algorithm checksum


【解决方案1】:

您可以考虑在您的 User 模型上使用“revision”或“lastModified”属性。

根据您的框架和需求,您也可以防止并发修改。

问候。

【讨论】:

  • revision 和 lastModified 的问题可能是即使没有修改实际内容并且允许更新,它们也会继续更新。
  • like 用户一直在更新他的名字,在数据库端我们只有空检查,所以当旧值更新时,它可以随着增加修订和更新 lastModified 一起插入,但实际上内容保持不变,这种实现可以很好地了解数据上次修改的时间,但我对数据完整性有疑问。
  • 我的意见是让 DB Framework (ORM) 来处理数据完整性、修订等...以这种方式(在服务类等中)
  • 是的,我同意这一点,但这是为了避免代码方面的复杂性,如果代码中没有,我们会将复杂性转移到数据库查询。
  • 对我不起作用,因为如果字段被更新并在下一次更新中恢复,这将返回误报。
【解决方案2】:

如果您可以访问数据库,那么我建议您创建一个新的列哈希。

例如请跟随这个脚本

drop database if exists test_md5;
create database test_md5;

use test_md5;

CREATE TABLE if not exists `test_users` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) not null,
  PRIMARY KEY (`id`)
);

CREATE TABLE if not exists `test_posts` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `title` text NOT NULL, 
  `user_id` bigint(20) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_post_user` (`user_id`),
  CONSTRAINT `fk_post_user` FOREIGN KEY (`user_id`) REFERENCES `test_users` (`id`)
);

-- Users 
insert into test_users(username) values('john');
insert into test_users(username) values('jane');

-- John's test_posts Content
insert into test_posts(title, user_id) values('hey i am john, this is my very first post', 1);
insert into test_posts(title, user_id) values('hey i am john, this is my very first post', 1);
insert into test_posts(title, user_id) values('hey i am john again, i\'ll be going off from website for couple of days', 1);

-- Jane's test_posts Content
insert into test_posts(title, user_id) values('hey i am jane, this website looks a biut dry', 2);

请注意,我的第二行与第一行的内容相同。 现在,当查询它们时,我为构成单行项或多个表的数据完整性的字段添加提取列。

当我们将posts.id column 添加到concat 函数时,它使行可区分。


SELECT posts.id, posts.title, users.username, 
md5(concat(posts.title, users.username)) 
as hash from test_posts as posts 
inner join test_users as users where posts.user_id = users.id

在第一次迭代中,您将返回 hash 以及数据。

在第二次迭代中,您将获得请求中的哈希值和来自 sql 响应或数据库层的哈希值,您可以比较这两个值并进一步决定还需要做什么。

另一种方法是,您为数据库中表示的每个模型实现有意义的equals and hashcode

另一种解决方案是将字符串转换为 JSON 并计算校验和并进行比较,但这效率较低,因为它涉及添加额外的 json 库,并且转换为 JSON 是一种昂贵的魔法。

参考这里:

https://ckhconsulting.com/row-or-rows-md5-hash-with-mysql/

【讨论】:

    【解决方案3】:

    一个不消耗太多资源的好方法是比较每个字段的值,当你发现差异时,比较可以停止

    例子:

    Roger Federer | Ferrari | Keyboard | Romeo
    Roger Federer | Ferrari | Keyboard2 | Juilet
    

    比较字段1(相同)->字段2(相同)->字段3(不同):停止比较

    【讨论】:

    • 这对我不起作用,因为我要覆盖旧值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多