Hibernate 获取带有字符串前缀的下一个 ID

Hibernate get next ID with string prefix

我有一个关于 Hibernate 中主键生成的问题。我正在维护现有的注册系统。当前设计使用字符串作为主键。规则类似于 "EXE" + max()。下面是 table 的样子。

+----------+---------------------------+----------------+
| ID       |   Email                   |   Name         |
+----------+---------------------------+----------------+
|EXE1      | email1@gmail.com          | Name 1         |
+----------+---------------------------+----------------+
|EXE5      | email5@gmail.com          | Name 5         |
+----------+---------------------------+----------------+
|EXE14     | email14@gmail.com         | Name 14        |
+----------+---------------------------+----------------+
|EXE15     | email15@gmail.com         | Name 15        |
+----------+---------------------------+----------------+

目前我正在使用下面的代码生成 ID。

Long rowCount = (Long) getSession().createCriteria(Exemption168DB.class).setProjection(Projections.rowCount()).uniqueResult();
if(rowCount == null)
    rowCount = 0L;
return String.format("%s%d", CommonConstant.EXEMPTION_KEY_PREFIX, rowCount + 1);

但问题是;它使用行计数来获取下一个序列数字。所以在上面的例子中,该方法将 return EXE5(这个 ID 已经存在于 table 中,因此抛出异常)因为 table 中的行数是 4,然后加1。我需要的是EXE16.

非常感谢任何帮助。额外信息,我们使用 Informix 作为数据库引擎。

创建自定义 ID 生成器 class 查询最后插入的 ID 并提取数字部分。 Select 字符串长度等于 ID 的最大字符串长度的所有 ID,降序排列并将结果集限制为 1。然后按照您在问题中所做的那样增加数字。

正如我在 中指出的那样,Informix 中可用的一种技术是使用触发器和 SERIAL 列。另一种技术是使用 SEQUENCE 和存储过程。

下面是序列加存储过程的一些演示代码:

CREATE SEQUENCE registry_seq
    INCREMENT BY 3
    START WITH 37
    MINVALUE 21
    MAXVALUE 299
    CYCLE;

CREATE PROCEDURE get_next_registry_id() RETURNING VARCHAR(10) AS registry_id;

    DEFINE i INTEGER;
    DEFINE r VARCHAR(10);
    SELECT registry_seq.NEXTVAL INTO i FROM "informix".SysTables WHERE tabid = 1;

    LET r = "EXE" || i;

    RETURN r;

END PROCEDURE;

CREATE TEMP TABLE registry
(
    id              VARCHAR(10) NOT NULL UNIQUE,
    email           VARCHAR(64) NOT NULL UNIQUE,
    name            VARCHAR(64) NOT NULL UNIQUE
);

INSERT INTO registry VALUES('EXE1', 'email1@gmail.com', 'Name 1');
INSERT INTO registry VALUES('EXE5', 'email5@gmail.com', 'Name 5');
INSERT INTO registry VALUES('EXE14', 'email14@gmail.com', 'Name 14');
INSERT INTO registry VALUES('EXE15', 'email15@gmail.com', 'Name 15');

INSERT INTO registry VALUES(get_next_registry_id(), 'email' || registry_seq.currval || '@example.com', 'User ID ' || registry_seq.currval);
INSERT INTO registry VALUES(get_next_registry_id(), 'email' || registry_seq.currval || '@example.com', 'User ID ' || registry_seq.currval);
INSERT INTO registry VALUES(get_next_registry_id(), 'email' || registry_seq.currval || '@example.com', 'User ID ' || registry_seq.currval);

SELECT * FROM registry ORDER BY id;

显然,您将为 CREATE SEQUENCE 语句选择不同的控制值。这些对我的测试工作半方便(开始在不同的 table 上工作)。

FROM "informix".systables WHERE tabid = 1 是 selecting 单行数据的标准 Informix 习惯用法。系统目录中记录了systables table tabid of 1。在现代版本的 Informix 上(意味着你应该 运行 的任何东西;虽然可能有些人仍然 运行 旧版本),你可以 select 从 sysmaster:sysdual (或者,如果你真的很安全,sysmaster:"informix".sysdual) 这是单行 table 单列。

最终输出为:

EXE1    email1@gmail.com        Name 1
EXE14   email14@gmail.com       Name 14
EXE15   email15@gmail.com       Name 15
EXE37   email37@example.com     User ID 37
EXE40   email40@example.com     User ID 40
EXE43   email43@example.com     User ID 43
EXE5    email5@gmail.com        Name 5

请注意,字母数字 ID 的缺点之一是排序顺序不是数字而是字典顺序。