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

Java Hibernate和PostgreSQL:我可以配置GenerationType.IDENTITY,其中每个id列';s的默认值来自共享序列?,java,hibernate,hibernate-annotations,Java,Hibernate,Hibernate Annotations,好的,我不是100%确定我是否真的想要这个,但目前这似乎是一个好主意 我按如下方式配置实体: @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id = 0; 如果让Hibernate生成表,结果是: id bigserial NOT NULL, CONSTRAINT test_pkey PRIMARY KEY (id) bigserial依次转换为默认值为: nextval('test_id_s

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

我按如下方式配置实体:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id = 0;
如果让Hibernate生成表,结果是:

  id bigserial NOT NULL,
  CONSTRAINT test_pkey PRIMARY KEY (id)
bigserial依次转换为默认值为:

nextval('test_id_seq'::regclass)
现在可以了,但我目前正在考虑对所有表使用单个序列,并希望默认值为:

nextval('my_global_sequence'::regclass)
也许我以后可以手动调整默认值,但是你知道我如何让hibernate自动定义这样的表吗?是否有一种方法可以推动我自己的CREATETABLE sql策略,该策略会为id列发出如下代码(未测试的sql语法):


请注意,我希望坚持使用标识策略,因为我希望避免任何“hi/lo乘以分配大小缓存序列”策略。有时,我需要通过pgAdmin插入一些手动行,而不必冒与hibernate发生任何id冲突的风险。所有其他策略对我来说都很神奇(=我不理解它们)。

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

以您的代码为例:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@SequenceGenerator(name="my_global_sequence")
private long id = 0;
使用此注释,可以为每个实体或实体组配置特定的序列生成器,甚至在任何地方都使用相同的序列生成器


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

我不知道如何使用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列被定义为bigserial,这将导致创建一个名为“test_id_seq”的序列。在我看来,GenerationType.IDENTITY似乎优先于任何@SequenceGenerator注释。
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)");
  }
}