Java Derby-如何处理对目标字段的添加
我希望为用户创建一个表并跟踪他们的目标。目标本身如果不是1000个,也可能是100个,并且会保存在他们自己的表中,但它不知道是谁完成了它们——它只会定义可用的目标Java Derby-如何处理对目标字段的添加,java,derby,bit-fields,Java,Derby,Bit Fields,我希望为用户创建一个表并跟踪他们的目标。目标本身如果不是1000个,也可能是100个,并且会保存在他们自己的表中,但它不知道是谁完成了它们——它只会定义可用的目标 Objective: ID | Name | Notes | ----+---------+---------+ | | | 现在,在Java环境中,用户将为目标设置一个Java.util.BitSet。所以我可以走了 /* in class User */ boolean has
Objective:
ID | Name | Notes |
----+---------+---------+
| | |
现在,在Java环境中,用户将为目标设置一个Java.util.BitSet。所以我可以走了
/* in class User */
boolean hasCompletedObjective(int objectiveNum) {
if(objectiveNum < 0 || objectivenum > objectives.length())
throw new IllegalArgumentException("Objective " + objectiveNum + " is invalid. Use a constant from class Objective.");
return objectives.get(objectivenum);
}
我的选项是什么,包括存储和封送到位集中?
是否存在java.util.BitSet的可行替代方案?
一般方法是否存在缺陷?我愿意接受各种想法
谢谢
*编辑:如果可能的话,我希望能够添加更多的目标,只需修改数据,而不是修改表。不过,我还是愿意接受各种想法 传统的方法根本不涉及位集。您有一个用户表、一个目标表和一个连接表,指示用户有哪些目标。比如:
create table users (
id integer primary key,
name varchar(100) not null
);
create table objectives (
id integer primary key,
name varchar(100) not null
);
create table user_objective (
user_id integer not null references users,
objective_id integer not null references objectives,
primary key (user_id, objective_id)
);
每当用户有一个目标时,您都会在联接表中放入一行,指示该事实
如果要将结果放入用户的位集中,请通过联接表将用户外部联接到目标表上,这样每个目标都会返回一行,其中有一列,例如,每个联接的目标都有一个1,如果没有联接,则返回0
传统的方法也是在Java端使用集合,而不是位集合。这非常好地映射到联接表上。你考虑过这样做吗
如果您担心内存消耗,那么一个集合将为用户实际拥有的每个目标使用大约一个指针;位集将根据可能的目标使用位。大多数JVM都有32位指针(只有旧的或大量堆积的64位JVM才有64位指针),因此如果每个用户的平均目标少于可能目标的1/32,那么集合将使用更少的内存。有一些groovy数据结构能够比这两种结构更紧凑地存储这些信息,但让我们把它留给另一个问题。[戴上假胡子]
将位集存储为。首先简单地序列化它,然后如果您想要更高的空间效率,尝试通过DeflaterOutputStream将结果推送到数据库。为了获得更好的空间和时间效率,请尝试中使用的位图压缩方法,该方法将位集分解为31位块,然后运行长度编码所有零块,将文本和运行块与鉴别器位一起打包为32位字
如果您知道只在从数据库获取目标位集的结果集仍然打开时才查看目标位集,那么可以编写一个新的位集类,该类包装Blob接口,并在getBytes上实现get。这避免了必须将整个BLOB读入内存以检查几个特定的位,并且如果您确实想查看所有的值,至少避免了必须为位集分配单独的缓冲区。请注意,使用压缩位集实现这一点需要相当多的技巧
请注意,这种方法没有参考完整性,也没有查询用户目标关系的能力,对于将来不同的数据使用几乎没有灵活性,正是这种方法。我希望在一次查询中获得所有用户数据(不想听起来过早,但需要快速登录。)由于您建议的user\u objective表是垂直增长的,这是否会使我的单个查询希望变得不可能?是的。您需要两个查询,一个是来自用户的信息,一个是来自user\u objective。我有一个要求,即所有用户数据都应在单个查询中返回。此外,上面描述的方法将使用整行重新查询呈现可以且应该缩减为单个字节的内容。用户\目标表的空间实际上是其应有空间的一百倍。(假设用户\标识为32位,对象\标识为32位,隐式行\标识为32位,总共96个字节)。我预计大约10000个用户,每个用户有大约300个目标。这应该是大约3MB的数据,而不是288Mb。随着目标和用户的增长,它根本无法扩展。这并不是说我不喜欢这种方法-我喜欢它的显式性,这肯定会简化调试/开发过程。但作为两个数量级的工具,它是不可扩展的ss对于存储的效率似乎比我现在愿意接受的要高。我不是一个喜欢过早优化的人,但我知道这将是不可伸缩的。288 MB对于数据库来说不是特别大的数量;它肯定比3 MB多得多,但没有可伸缩性问题。另外,担心可伸缩性和使用Derby对我来说,这似乎是一个奇怪的组合!你知道吗,你的名字、代表、徽章和可爱的粉色小图标都和另一个回答的人一样?如果不是因为你的面部毛发,我会认为你是同一个人!开玩笑的话,缺乏参照完整性实际上是我很看重的东西。我绝对是显性而非隐性wh的粉丝在实用之前。关于第二个,整个目标位集需要在登录阶段加载到内存中。用户可用的选项在很大程度上取决于已经完成的目标。另外,感谢您的坚持(明白吗?这是关于数据库的…好吧,我不会放弃我的日常工作…)在这里帮助我。很多人会冲出来说“如果你不想做,那就别费心做!”或者像这样疯狂的事情。@glowcoder:我在玩一个长游戏。如果你实施这个,那么六个月后,它会咬你的屁股,你会转过身说,“该死,那个刮胡子的家伙一直都是对的!”.@Tom除了引用完整性(目标有明确的文档记录,因此改革它们的绑定不会引起太多的关注)还有其他严重问题需要解决吗
create table users (
id integer primary key,
name varchar(100) not null
);
create table objectives (
id integer primary key,
name varchar(100) not null
);
create table user_objective (
user_id integer not null references users,
objective_id integer not null references objectives,
primary key (user_id, objective_id)
);