Приложение Java Springboot не увеличивает идентификатор при записи в базу данных Oracle, вместо этого я получаю сообщение об ошибке

#java #oracle #spring-boot #h2 #liquibase

#java #Oracle #spring-boot #h2 #liquibase

Вопрос:

У меня есть приложение java springboot, в котором я создаю таблицу с liquibase, в которую я хочу записать историю объектов. Однако идентификатор объекта не увеличивается, вместо этого я получаю сообщение об ошибке, что база данных не может записать объект в базу данных, когда идентификатор равен нулю.

Мой объект, который я хочу записать в базу данных, выглядит следующим образом:

 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>
  

У кого-нибудь есть идеи по этому поводу?
Спасибо 🙂

Ответ №1:

Для автоматической генерации id вам необходимо изменить @GeneratedValue и добавить @SequenceGenerator аннотации в History классе.
ChangeLog Перед созданием новой таблицы создайте последовательность.


  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" , если столбец является первичным ключом. Поскольку первичный ключ уже не является обнуляемым и уникальным.

Ответ №2:

Привет, я нашел решение. Кажется, что Oracle нужна последовательность для увеличения идентификатора объекта. Теперь мой объект истории выглядит так:

 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, но эта ошибка не была найдена.

В любом случае, я надеюсь, что это кому-нибудь поможет 🙂