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 的缺点之一是排序顺序不是数字而是字典顺序。
我有一个关于 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。然后按照您在问题中所做的那样增加数字。
正如我在
下面是序列加存储过程的一些演示代码:
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 的缺点之一是排序顺序不是数字而是字典顺序。