自动递增在使用Hibernate向PostgreSQL添加项时不会发生。

huangapple go评论110阅读模式
英文:

Auto incrementing does not occur when adding an item in PostgreSQL using Hibernate

问题

我在PostgreSQL中创建了一个包含个人数据的表,并将列 "id" 标记为类型 'SERIAL' 和 '主键','非空'。

以下是创建脚本:

CREATE TABLE people (
  id serial NOT NULL,
  name varchar(15),
  surname varchar(25),
  department varchar(20),
  salary int,
  PRIMARY KEY (id)
);

然后,我为我的表创建了一个实体类:

package hibernate_test.entity;
import jakarta.persistence.*;

@Entity
@Table(name = "people")
public class Employee {
    @Id
    @Column(name = "id")
    private int id;
    @Column(name = "name")
    private String name;
    @Column(name = "surname")
    private String surname;
    @Column(name = "department")
    private String department;
    @Column(name = "salary")
    private int salary;

    public Employee() {
    }

    public Employee(String name, String surname, String department, int salary) {
        this.name = name;
        this.surname = surname;
        this.department = department;
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", surname='" + surname + '\'' +
                ", department='" + department + '\'' +
                ", salary=" + salary +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }
}

接下来,我编写了一个程序来向我的表中添加记录:

package hibernate_test;

import hibernate_test.entity.Employee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test1 {
    public static void main(String[] args) {
        SessionFactory factory = new Configuration()
                .configure("hibernate.cfg.xml")
                .addAnnotatedClass(Employee.class)
                .buildSessionFactory();

        Session session = factory.getCurrentSession();
        Employee emp = new Employee("Jack", "Jack", "IT", 5000);

        try {
            session.beginTransaction();
            session.save(emp);
            session.getTransaction().commit();

        } finally {
            factory.close();
        }
    }
}

当我运行此代码时,第一条记录被添加到表中,但id是0。我认为id应该从1开始,因为我在id中指定了类型 'SERIAL'。当我尝试添加另一项时,出现错误:

错误表明不能有两条id为0的记录,但我没有直接将id值传递给构造函数。Hibernate应该自己递增id,并且理想情况下从1开始。

如果可以的话,我会很高兴帮助你找出我哪里出错了。

英文:

I created a table in PostgeSQL with data for a person and marked the column "id" with the type 'SERIAL' as 'primary key', 'not null'

CREATE Script:

CREATE TABLE people (
id serial NOT NULL,
name varchar(15),
surname varchar(25),
department varchar(20),
salary int,
PRIMARY KEY (id)
);

Then I created an Entity class for my table

package hibernate_test.entity;
import jakarta.persistence.*;
@Entity
@Table(name = "people")
public class Employee {
@Id
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
@Column(name = "surname")
private String surname;
@Column(name = "department")
private String department;
@Column(name = "salary")
private int salary;
public Employee() {
}
public Employee(String name, String surname, String department, int salary) {
this.name = name;
this.surname = surname;
this.department = department;
this.salary = salary;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", name='" + name + '\'' +
", surname='" + surname + '\'' +
", department='" + department + '\'' +
", salary=" + salary +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}

Next, I wrote a program that adds a record to my table

package hibernate_test;
import hibernate_test.entity.Employee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Test1 {
public static void main(String[] args) {
SessionFactory factory = new Configuration()
.configure("hibernate.cfg.xml")
.addAnnotatedClass(Employee.class)
.buildSessionFactory();
Session session = factory.getCurrentSession();
Employee emp = new Employee("Jack", "Jack", "IT", 5000);
try {
session.beginTransaction();
session.save(emp);
session.getTransaction().commit();
}finally {
factory.close();
}
}
}

When I run this code, the first record is added to the table, but the id is at index 0. I think the index should start at 1 because I specified the type 'SERIAL' in the id.
When I try to add another item, an error occurs:

09:09:05.911 [main] INFO org.hibernate.Version -- HHH000412: Hibernate ORM core version 6.2.6.Final
09:09:05.916 [main] INFO org.hibernate.cfg.Environment -- HHH000406: Using bytecode reflection optimizer
09:09:06.366 [main] WARN org.hibernate.orm.connections.pooling -- HHH10001002: Using built-in connection pool (not intended for production use)
09:09:06.369 [main] INFO org.hibernate.orm.connections.pooling -- HHH10001005: Loaded JDBC driver class: org.postgresql.Driver
09:09:06.369 [main] INFO org.hibernate.orm.connections.pooling -- HHH10001012: Connecting with JDBC URL [jdbc:postgresql://127.0.0.1:5432/learnhbn]
09:09:06.369 [main] INFO org.hibernate.orm.connections.pooling -- HHH10001001: Connection properties: {password=****, user=postgres}
09:09:06.369 [main] INFO org.hibernate.orm.connections.pooling -- HHH10001003: Autocommit mode: false
09:09:06.373 [main] INFO org.hibernate.orm.connections.pooling -- HHH10001115: Connection pool size: 20 (min=1)
09:09:06.796 [main] INFO org.hibernate.bytecode.internal.BytecodeProviderInitiator -- HHH000021: Bytecode provider name : bytebuddy
Hibernate: insert into people (department,name,salary,surname,id) values (?,?,?,?,?)
09:09:07.648 [main] WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper -- SQL Error: 0, SQLState: 23505
09:09:07.648 [main] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper -- ПОМИЛКА: повторювані значення ключа порушують обмеження унікальності "people_pkey"
Подробности: Ключ (id)=(0) вже існує.
09:09:07.656 [main] INFO org.hibernate.orm.connections.pooling -- HHH10001008: Cleaning up connection pool [jdbc:postgresql://127.0.0.1:5432/learnhbn]
Exception in thread "main" org.hibernate.exception.ConstraintViolationException: could not execute statement [ПОМИЛКА: повторювані значення ключа порушують обмеження унікальності "people_pkey"
Подробности: Ключ (id)=(0) вже існує.] [insert into people (department,name,salary,surname,id) values (?,?,?,?,?)]
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:95)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:56)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:108)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:278)
at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.performNonBatchedMutation(AbstractMutationExecutor.java:108)
at org.hibernate.engine.jdbc.mutation.internal.MutationExecutorSingleNonBatched.performNonBatchedOperations(MutationExecutorSingleNonBatched.java:40)
at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.execute(AbstractMutationExecutor.java:53)
at org.hibernate.persister.entity.mutation.InsertCoordinator.doStaticInserts(InsertCoordinator.java:170)
at org.hibernate.persister.entity.mutation.InsertCoordinator.coordinateInsert(InsertCoordinator.java:112)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2761)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:102)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:633)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:502)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:358)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1412)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:485)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2301)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:1966)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:439)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:169)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:267)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
at hibernate_test.Test1.main(Test1.java:21)
Caused by: org.postgresql.util.PSQLException: ПОМИЛКА: повторювані значення ключа порушують обмеження унікальності "people_pkey"
Подробности: Ключ (id)=(0) вже існує.
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2713)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2401)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:368)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:498)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:415)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:190)
at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:152)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:275)
... 21 more
Process finished with exit code 1

The error indicates that there can't be two records with index 0, but I don't pass any id value directly to the constructor. Hibernate should increment the id to one itself, and ideally start with one

I will be glad if you can help me figure out where I am making a mistake

答案1

得分: 1

答复来自 M. Deinum

您没有在 @Id 字段上指定策略。应该在那里使用 @GeneratedValue 来告诉Hibernate数据库会生成标识符。

英文:

Answer from M. Deinum:

You didn't specify a strategy on the @Id field. There should be an @GeneratedValue on there to indicate to Hibernate that the database will generate the identifier.

huangapple
  • 本文由 发表于 2023年7月18日 14:14:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76709961.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定