8

我正在使用一个权限模型,其中我有一个 table user_permissions。该表将包含一个或多个具有特定 bigint 的列。我将使用每个十进制数的位与某些权限规则进行比较(位位置将是权限规则,值将是规则的条件activenot active)。

这种方法的问题在于,在使用诸如 bigint 之类的数字时,我可以使用的位数有限。

在这种情况下,我可以在跨数据库环境中使用的最佳列类型是什么?

这些标签代表了我的目标技术,因此与这些技术相关的任何其他解决方案都值得赞赏。

我正在考虑使用 @Lob 注释来存储大数据,这是最佳做法吗?

更新:user_permission 表以 1:1 的关系扩展了用户,并具有 bin_create、bin_read、bin_update、bin_delete 等 bigint 字段,这些字段将二进制数据保存为十进制数。

为了澄清这个问题:我正在考虑使用按位运算符比较权限。因此,假设我有一个权限值为 10(1010) 的用户,以及一个需要 13 (1101) 的操作。所以 10 & 13 == 8 (1000) -> 用户有一个与操作所需权限匹配的权限,所以我可以允许或拒绝(取决于应用程序规则定义哪个)。但是通过这种方法,我可以处理的位数有限(假设我增加了要考虑的权限,所以数字也会增加)。最大的 bigint 值是 ~9223372036854775807,这给了我二进制 1111111111111111111111111111111111111111111111111111111111111111111111111,每个字段有 ~60 个块和权限可能性。

4

3 回答 3

1

如果这是您关注的字段中可以容纳的数据量,为什么不将数字存储为 varchar?据我所知,几乎任何数据库都可以让您至少达到 varchar(255)。如果您需要的数字超过 255 位,则可以将其编码为 base 64 以将其压缩得更多。如果我的心算是正确的,那么您可以使用 255 个字符 * 每个字符 6 位 = 1530 个不同的位可供使用。如果您需要更多,我可能会建议您的权限模型有点过分。

That's assuming that you're trying to crowd the data into a smallish space in the database. Your question isn't entirely clear on what you're trying to solve for. On the other end of the spectrum, you could unpack the bits and save each bit to its own field or its own row. For example, user_permissions could be a table with two columns: user and permission, where each row is one permission granted to one user.

于 2013-02-15T05:38:17.200 回答
1

如果您想以最佳方式存储数据,则必须命名要优化的目标。

这是 MySQL 的最佳解决方案(通过定义BINARY(32)),您可以在您喜欢的数据库上尝试类似的东西:

@Column(columnDefinition = "BINARY(32)", length = 32, nullable = false)
private byte[] bits;

有时,对于某些 JPA 提供程序和数据库,列定义以Lob. 这不是最好的解决方案,因为读取 aLob是一个外部(非常昂贵的)操作。尝试更改提供程序或数据库(如果您使用的是纯 JPA,则可以尝试)。

替换Lobs 的选项例如是数字列(您可以使用例如 4 列 64 位宽度或类似的列)。如果您想要一个好的解决方案,这些容器列甚至可以@Embedded进入您的主类。但这一切都取决于您的数据库。

这样,您将拥有 256 位(32 字节),无需任何转换和进一步计算,并且您可以根据需要扩展范围。但是,在更改列定义时必须小心。

于 2013-02-18T23:33:56.947 回答
0

有两种不同的方法:

1)漂亮的数据模型

一行(您的示例中的用户)可以具有值(这里是一位用户权限或布尔值),您不知道可能有多少值,即值的数量基本上是无限的。SQL 中处理此问题的常规方法是子表:

您创建一个表(以及用于映射/注释的 Java 类)UserPermission,其中包含作为外键的用户 ID、权限 ID 和布尔值。用户 ID 和权限 ID 是此表的唯一键(如果您愿意,可以添加一个 ID 作为不同的主键)。如果您想进行一些审核,您甚至可以为授予权限的用户添加列、完成日期等,但这不是必需的。

如果您想让它更漂亮,那么您还可以创建一个表(和 Java 类)权限,其中包含权限 ID、权限名称以及可能的其他信息。

此解决方案需要比您的想法更多的数据库空间,但请记住,与数据库中的其他数据相比,您不会有这么多的用户,因此额外的数量无关紧要。

2)快速解决方案:

如果带有额外表的解决方案需要很多开销,因为您的权限并不重要,并且您担心整数可能会很短,那么您可以使用 Java 类型BigInteger(该类型允许位操作)并将其与@Column注解映射到aNUMBERDECIMAL在数据库中。

请记住,数据库的大小NUMBER也是有限的(例如 Oracle 最多允许 10^40)。如果这可能是一个问题,那么您必须使用解决方案 1)。

解决方案 2) 的另一个缺点是,您永远不能使用索引来获取权限。(选择具有特定权限集的所有用户永远不会超过索引。)

我总是会使用解决方案 1)。

于 2013-02-15T08:01:32.513 回答