英文:
Java Springboot application is not increasing ID when writing in Oracle database instead I get an error
问题
我有一个Java Spring Boot应用程序,在其中我使用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>
有人对此有什么想法吗?谢谢
英文:
I have a java springboot application in which I am creating a table with liquibase in which I want to write an object history. However the id of the object is not increasing, instead I get an error that the database cannot write an object to the database when the id is null.
My object I want to write in the database looks like this:
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;
...
}
My liquibase changelog looks like this:
<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>
Has anybody ideas on this?
Thank you
答案1
得分: 0
嗨,我找到了解决方案。
似乎 Oracle 需要一个序列来增加对象的 ID。
我的 history 对象现在看起来像这样:
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 数据库上测试了我的变更日志,但没有发现此错误。
无论如何,希望这能帮助任何人 :)
英文:
Hi I found the solution.
It seems that Oracle needs a sequence to increase the id of an object.
My history object looks now like this:
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;
...
}
And my liquibase changelog looks like this:
<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>
Attention: The cache size has to be 2 or bigger.
I tested my changelog with h2 database, but this error was not found.
Anyway, I hope this helps anybody
答案2
得分: 0
自动生成id
需要在History
类中更改@GeneratedValue
并添加@SequenceGenerator
注解。
在创建新表之前,在ChangeLog
中创建序列。
- 添加所需的注解
@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;
- 在变更日志中添加标签以创建序列。可选地,您可以删除一些不必要的标签参数:
<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"
。因为主键已经是非空且唯一的。
英文:
To auto generate id
you need to change @GeneratedValue
and add @SequenceGenerator
annotations in History
class.
In ChangeLog
before creating new table create sequence.
- Add required annotations
@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;
- Add tag in change log to create sequence. Optional you can remove some unnecessary tag parameters:
<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>
This is the way how I work with auto increment. I can ensure it works.
Additional info about liquibase change logs:
- If you use oracle you don't need to write names in upper case, because it might not work if you going to change database type (not oracle). Oracle automatically converts i.e. column names to upper case.
- You can remove
nullable="false"
if column is primary key. Because primary key is already not nullable and unique.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论