Hibernate和PostgreSQL:我可以配置GenerationType.IDENTITY,其中每个id列的默认值来自共享序列吗?



好的,我不能100%确定我是否真的想要这个,但目前这似乎是个好主意。

我这样配置我的实体:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id = 0;

如果我让Hibernate生成表,结果是:

  id bigserial NOT NULL,
  CONSTRAINT test_pkey PRIMARY KEY (id)

bigserial依次转换为默认值为:的bigint

nextval('test_id_seq'::regclass)

现在可以了,但我目前正在考虑对所有表使用单一序列,并希望默认值为:

nextval('my_global_sequence'::regclass)

也许我以后可以手动调整默认值,但你知道我如何告诉hibernate自动定义这样的表吗?有没有一种方法可以推动我自己的创建表sql策略,为id列发布这样的代码(未经测试的sql语法):

id bigint NOT NULL DEFAULT = nextval('my_global_sequence'::regclass)

请注意,我希望坚持使用IDENTITY策略,因为我希望避免任何"hi/lo倍增分配大小缓存序列"策略。有时,我需要通过pgAdmin插入一些手动行,而不会冒与hibernate发生任何id冲突的风险。所有其他策略对我来说都像魔术。

我不知道如何使用hibernate来实现这一点。我目前的解决方案只是一个普通的旧JDBC/SQL逻辑,我在每次启动时都会执行它。到目前为止,我对此感到非常高兴。

Connection connection = DriverManager.getConnection(dbUrl, dbUser, dbPassword);
String catalog = connection.getCatalog();
String schema = "public";
DatabaseMetaData databaseMetaData = connection.getMetaData();
ResultSet tablesResultSet = databaseMetaData.getTables(catalog, schema, null, new String[] { "TABLE" });
while(tablesResultSet.next())
{
  String tableName = tablesResultSet.getString("TABLE_NAME");
  LOGGER.info("updating table: '" + tableName + "', setting global sequence");
  // update primary keys to global sequence
  {
    //        LOGGER.info("setting global sequence for '" + tableName + "'.id");
    connection.createStatement().execute("ALTER TABLE "" + tableName + "" ALTER COLUMN id TYPE bigint;");
    connection.createStatement().execute("ALTER TABLE "" + tableName + "" ALTER COLUMN id SET NOT NULL;");
    connection.createStatement().execute("ALTER TABLE "" + tableName + "" ALTER COLUMN id SET DEFAULT nextval('my_global_sequence'::regclass)");
  }
}

您可以在id上使用注释来确定要使用的序列生成器:

以您的代码为例:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@SequenceGenerator(name="my_global_sequence")
private long id = 0;

使用此注释,可以为每个实体或实体组配置特定的序列生成器,甚至可以在任何地方使用相同的序列生成器。

需要注意的是,您必须为每个拥有的实体定义该注释

相关内容

  • 没有找到相关文章

最新更新