Java Hibernate和PostgreSQL:我可以配置GenerationType.IDENTITY,其中每个id列';s的默认值来自共享序列?
好的,我不是100%确定我是否真的想要这个,但目前这似乎是一个好主意 我按如下方式配置实体: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
@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)");
}
}