Java 在 Oracle 数据库中写入时,Springboot 应用程序没有增加 ID,而是出现错误

Java Springboot application is not increasing ID when writing in Oracle database instead I get an error

我有一个 java springboot 应用程序,我在其中创建了一个 table with liquibase 我想在其中编写对象历史记录。但是对象的id并没有增加,而是我得到一个错误,当id为null时,数据库无法将对象写入数据库。

我想在数据库中写入的对象如下所示:

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "history")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class History{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID", nullable = false, updatable = false)
    private long id;
    @Column(name = "name", nullable = true)
    private String name;
    ...
}

我的 liquibase 更新日志如下所示:

<databaseChangeLog
        xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
        xmlns='http://www.liquibase.org/xml/ns/dbchangelog'
        xsi:schemaLocation='http://www.liquibase.org/xml/ns/dbchangelog
                            http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd'>

    <changeSet id='01-create table history' author='M. K.'>
        <createTable tableName='history'
                     remarks='A table to contain all history.'>
            <column autoIncrement='true' name='ID'
                    type='INTEGER'>
                <constraints nullable='false' primaryKey='true' primaryKeyName='HISTORYKEY'/>
            </column>
            <column name='NAME' type='varchar(100)'>
                <constraints nullable='true'/>
            </column>
...

        </createTable>
    </changeSet>
</databaseChangeLog>

有人对此有想法吗? 谢谢:)

您好,我找到了解决方案。 看来Oracle需要一个序列来增加一个对象的id。 我的历史对象现在看起来像这样:

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "history")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class History {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "HISTORYSEQ")
    @SequenceGenerator(name = "HISTORYSEQ", sequenceName = "HISTORYSEQ", allocationSize = 1)
    @Column(name = "ID", nullable = false, updatable = false)
    private long id;
    @Column(name = "name", nullable = true)
    private String name;
...
}

我的 liquibase 变更日志如下所示:

<databaseChangeLog
        xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
        xmlns='http://www.liquibase.org/xml/ns/dbchangelog'
        xsi:schemaLocation='http://www.liquibase.org/xml/ns/dbchangelog
                            http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd'>

    <changeSet id='01-create table history' author='M. K.'>

                <createSequence  startValue="1" incrementBy="1" ordered="true" sequenceName="HISTORYSEQ" maxValue="9223372036854775807" minValue="1" cacheSize="2"/>       

        <createTable tableName='history'
                     remarks='A table to contain all history.'>
            <column name='ID' type='INTEGER'>
                <constraints nullable='false' primaryKey='true'/>
            </column>
            <column name='NAME' type='varchar(100)'>
                <constraints nullable='true'/>
            </column>
...

        </createTable>
    </changeSet>
</databaseChangeLog>

注意:缓存大小必须为 2 或更大。

我用 h2 数据库测试了我的更新日志,但没有发现这个错误。

无论如何,我希望这对任何人都有帮助:)

要自动生成 id 您需要更改 @GeneratedValue 并在 History class.
中添加 @SequenceGenerator 注释 在 ChangeLog 之前创建新的 table 创建序列。


  1. 添加所需的注释
@Id
@SequenceGenerator(name = "seq_history", sequenceName = "seq_history_id", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_history")
@Column(unique = true, updatable = false, nullable = false)
private long id;
  1. 在更改日志中添加标签以创建序列。可选的你可以删除一些不必要的标签参数:
<changeSet id='1' author='M. K.'>

    <createSequence incrementBy="1" sequenceName="seq_history_id" startValue="1"/>

    <createTable tableName='history'>
        <column name='id' type='bigint'>
            <constraints primaryKey='true' primaryKeyName='pk_history'/>
        </column>
...

    </createTable>
</changeSet>

这就是我使用自动增量的方式。我可以确保它有效。


关于 liquibase 更改日志的其他信息:

  • 如果您使用 oracle,则不需要大写名称,因为如果您要更改数据库类型(不是 oracle),它可能无法正常工作。 Oracle 自动将列名转换为大写。
  • 如果列是主键,您可以删除 nullable="false"。因为主键已经不可为空且唯一。