Java 为什么liquibase总是使用自己的序列?

Java 为什么liquibase总是使用自己的序列?,java,postgresql,spring-boot,spring-data-jpa,liquibase,Java,Postgresql,Spring Boot,Spring Data Jpa,Liquibase,我正在使用liquibase作为我当前项目的迁移工具 问题是,我试图使用自定义序列为实体自动生成ID,但出现了一些错误 我定义了一个实体表和自定义序列,如下所示: <databaseChangeLog> <changeSet id="create_orders_table" author="I am"> <createTable tableName="ORDERS"> <column name="id" type="SERIAL

我正在使用liquibase作为我当前项目的迁移工具

问题是,我试图使用自定义序列为实体自动生成ID,但出现了一些错误

我定义了一个实体表和自定义序列,如下所示:

<databaseChangeLog>
<changeSet id="create_orders_table" author="I am">
    <createTable tableName="ORDERS">
        <column name="id"  type="SERIAL" valueComputed="SEQ_ORDERS.NEXTVAL" valueSequenceCurrent="SEQ_ORDERS.CURRENT"  valueSequenceNext="SEQ_ORDERS.NEXTVAL" defaultValueSequenceNext="SEQ_ORDERS.NEXTVAL">
            <constraints primaryKey="true" unique="true"/>
        </column>
        <column name="number" type="VARCHAR(64)"/>
        ...
    </createTable>
</changeSet>
<changeSet id="add_sequence" author="I am">
    <createSequence sequenceName="SEQ_ORDERS" cycle="false" minValue="1" maxValue="9223372036854775807" startValue="1" incrementBy="1"/>
</changeSet>
</databaseChangeLog>
首先让我感到不可预测的是,为什么liquibase编写了自己的
orders\u id\u seq
而不是我的
seq\u orders

接下来,我编写了一个典型的JPA代码,并使用Spring进行了测试:

@Entity(name = "ORDERS")
public class Order {

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ORDERS_ID_GEN")
  @SequenceGenerator(name = "ORDERS_ID_GEN", sequenceName = "SEQ_ORDERS")
  private long id;

  private String number; 
  //... getters,setters and other stuff
}

public interface OrderRepository extends JpaRepository<Order,Long> {}
在测试日志中,我看到:

Hibernate: select nextval ('seq_orders')
...
java.lang.AssertionError: 
Expected: is <Order(id=50, number=order-n-01, ...>
   but: was null

如果指定
serial
作为数据类型,则不应指定任何默认值,因为Postgres。序列和
命令\u id_seq
,默认值由Postgres在使用
serial
时自动创建,它不是由Liquibase创建的

因此,如果您想使用自己的序列(无论出于何种原因),请将列指定为
integer
,并使用
nextval()
指定一个
defaultValueComputed
。在创建表之前,还需要创建序列

此外,获取下一个值的语法不是Postgres中的
sequence.nextval
,而是
nextval('sequence')

<databaseChangeLog>
<changeSet id="add_sequence" author="I am">
    <createSequence sequenceName="SEQ_ORDERS" cycle="false" minValue="1" maxValue="9223372036854775807" startValue="1" incrementBy="1"/>
</changeSet>

<changeSet id="create_orders_table" author="I am">
    <createTable tableName="ORDERS">
        <column name="id"  type="integer" defaultValueComputed="nextval('seq_orders')>
            <constraints primaryKey="true" unique="true"/>
        </column>
        <column name="number" type="VARCHAR(64)"/>
        ...
    </createTable>
</changeSet>
</databaseChangeLog>


如果指定
serial
作为数据类型,则不应指定任何默认值,因为Postgres。序列和
命令\u id_seq
,默认值由Postgres在使用
serial
时自动创建,它不是由Liquibase创建的

因此,如果您想使用自己的序列(无论出于何种原因),请将列指定为
integer
,并使用
nextval()
指定一个
defaultValueComputed
。在创建表之前,还需要创建序列

此外,获取下一个值的语法不是Postgres中的
sequence.nextval
,而是
nextval('sequence')

<databaseChangeLog>
<changeSet id="add_sequence" author="I am">
    <createSequence sequenceName="SEQ_ORDERS" cycle="false" minValue="1" maxValue="9223372036854775807" startValue="1" incrementBy="1"/>
</changeSet>

<changeSet id="create_orders_table" author="I am">
    <createTable tableName="ORDERS">
        <column name="id"  type="integer" defaultValueComputed="nextval('seq_orders')>
            <constraints primaryKey="true" unique="true"/>
        </column>
        <column name="number" type="VARCHAR(64)"/>
        ...
    </createTable>
</changeSet>
</databaseChangeLog>


是的,这样的变更日志让postgreSQL使用我的序列,但我还是得到了50,51,52个ID。@rvit34:可能是你的模糊层中的映射有问题-我不使用Hibernate,所以我不能帮你)。你可能想问一个单独的问题(关于SO的问题应该只包含一个问题)。但这听起来像是Hibernate中的某种缓存。或者您是否使用
cache=“50”
创建了序列?正如我在PgAdmin中看到的那样,我的序列订单的缓存是1Thanks。我发现Hibernate在默认情况下以50块的形式分配序列值,以优化插入性能。为了防止需要在@SequenceGeneratorYeah上指定
allocationSize=1
,这样的更改日志使postgreSQL使用我的序列,但我还是得到了50,51,52个ID。@rvit34:可能是混淆层中的映射有问题-我没有使用Hibernate,所以我无法帮助您)。你可能想问一个单独的问题(关于SO的问题应该只包含一个问题)。但这听起来像是Hibernate中的某种缓存。或者您是否使用
cache=“50”
创建了序列?正如我在PgAdmin中看到的那样,我的序列订单的缓存是1Thanks。我发现Hibernate在默认情况下以50块的形式分配序列值,以优化插入性能。为防止出现这种情况,需要在@SequenceGenerator上指定
allocationSize=1
spring.jpa.hibernate.ddl-auto=none
spring.jpa.generate-ddl=false
spring.jpa.database=postgresql

spring.datasource.initialize=false
spring.datasource.username=postgres
spring.datasource.password=********
spring.datasource.url=jdbc:postgresql://localhost:5432/ORDERS_TEST
spring.datasource.driver-class-name=org.postgresql.Driver

liquibase.change-log=classpath:/db/changelog/changelog-master.xml
<databaseChangeLog>
<changeSet id="add_sequence" author="I am">
    <createSequence sequenceName="SEQ_ORDERS" cycle="false" minValue="1" maxValue="9223372036854775807" startValue="1" incrementBy="1"/>
</changeSet>

<changeSet id="create_orders_table" author="I am">
    <createTable tableName="ORDERS">
        <column name="id"  type="integer" defaultValueComputed="nextval('seq_orders')>
            <constraints primaryKey="true" unique="true"/>
        </column>
        <column name="number" type="VARCHAR(64)"/>
        ...
    </createTable>
</changeSet>
</databaseChangeLog>