Java @Id注释在Oracle的Hibernate中不起作用

Java @Id注释在Oracle的Hibernate中不起作用,java,database,oracle,hibernate,Java,Database,Oracle,Hibernate,我正在从中学习hibernate,并试图保存一本实体书 import javax.persistence.Entity; import javax.persistence.Id; @Entity public class Book { @Id private int id; private String name; public String getName() { return name; } public void setName(String name) {

我正在从中学习hibernate,并试图保存一本实体书

import javax.persistence.Entity;



import javax.persistence.Id;


@Entity
public class Book {

@Id

private int id;

private String name;

public String getName() {
    return name;
}

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



    Book book1 = new Book();

    book1.setName("Sample");
    session.save(book1);
但此代码只工作一次,并且在Books表中没有数据时也工作一次,因为每次它都生成“0”作为主键id。下面是异常跟踪

ERROR: HHH000346: Error during managed flush 

[org.hibernate.exception.ConstraintViolationException: could not execute statement]
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:147)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1403)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:473)
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3133)
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2370)
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:467)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:146)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:220)

Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (SPRING.SYS_C0015610) violated

    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399)
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059)
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
    at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587)
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:225)
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:53)
    at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:943)
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1150)
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:4798)
    at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:4875)
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1361)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)
    ... 19 more
书上说:

默认情况下,@Id注释将自动确定最合适的主注释 要使用的密钥生成策略也可以通过应用@GeneratedValue来覆盖该策略 注释

但是,如果我将@GeneratedValue注释与@ID一起使用,则代码可以正常工作,并且每次生成一个新的主键ID。这种情况对我来说没有意义。我是否遗漏了任何内容或是否存在任何db特定问题

CREATE TABLE BOOK(
ID INTEGER,
NAME VARCHAR2(50)
);

ALTER TABLE BOOK ADD PRIMARY KEY(ID);
如果没有元素,则使用Hibernate指定为默认生成器策略。在这种情况下,应用程序将分配实体的id。 如果您希望hibernate负责自动生成id,那么应该使用GeneratedValue或任何其他id生成策略

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
下面是一些例子

您的id类型为int

private int id;
当您第一次插入值时,jvm将为id分配默认值0,以便hibernate轻松地插入值为0的id, 现在,当您再次尝试插入值时,因为并没有id生成器策略,然后jvm再次将id设置为默认值0;当hibernate尝试插入id为0的值时,则抛出ConstraintViolationException异常,因为数据库中已经存在值为0的id。 因此,如果您希望hibernate自动为您的实体分配Id,您可以使用jpa特定的@GeneratedValue策略auto/IDENTITY/SEQUENCE/TABLE 或者另一个hibernate策略,它将负责为实体分配id

      increment
      sequence
      hilo
      native
      identity
      seqhilo
      uuid
      guid
      select
      foreign
      sequence-identity

布山,这是什么意思?默认情况下,Id注释将自动确定要使用的最合适的主键生成策略。您也可以通过应用GeneratedValue注释来覆盖该策略。我是否每次都需要覆盖该策略?@Steve作为一个例子,我已经提到,当您刚刚使用@Id时,然后使用分配策略意味着您将负责为您的实体分配Id,而不是休眠。另外,您能告诉我每次需要覆盖策略是什么意思吗?@Steve@Id只指定实体的主键,它不负责自动分配Id的值,如果您在@Id上使用,默认情况下,@Id注释将自动确定分配的策略意味着应用程序将在保存或持久化之前为对象分配一个identifierid值。这意味着您将编写代码,在实体保存之前在其中分配Id值。因此,如果您需要自动生成的Id值,那么您需要使用@GeneratedValue或另一个hibernate生成器策略,该策略将负责自动分配Id值。现在,m使用@GeneratedValuestrategy=GenerationType.AUTOon Id字段,代码工作正常。但是我尝试在另一台机器上使用相同的代码,我得到了一个异常跟踪。原因:java.sql.SQLSyntaxErrorException:ORA-02289:序列不存在。这是一个与数据库相关的问题吗?就像oracle数据库问题一样,您应该创建一个序列,我们称之为VEHICLE_SEQ。然后,您应该在您的id上添加以下注释:在java代码中:@GeneratedValuestrategy=GenerationType.AUTO,generator=SEQ@SequenceGeneratorname=SEQ,sequenceName=VEHICLE\ SEQ在db中创建序列:create sequence VEHICLE\ SEQ从1递增1开始;