【问题标题】:@Id annotation not working in Hibernate with Oracle@Id 注释在 Oracle 的 Hibernate 中不起作用
【发布时间】:2017-06-05 19:08:48
【问题描述】:

我正在向this book 学习休眠,我正在尝试保存实体书。

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 注解会自动确定最合适的primary 要使用的密钥生成策略——您也可以通过应用 @GeneratedValue 来覆盖它 注释

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

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

ALTER TABLE BOOK ADD PRIMARY KEY(ID);

【问题讨论】:

    标签: java database oracle hibernate


    【解决方案1】:

    如果没有元素,Hibernate 使用 assigned 作为默认生成器策略。在这种情况下,您的应用程序会分配实体的 id。 如果您希望 hibernate 会处理自动生成 id,那么您应该使用 GeneratedValue 或任何其他 id 生成策略

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    

    here 是一些例子

    你的id类型是int

    private int id;
    

    当你第一次插入值时 jvm 会分配 id 默认值 0 所以休眠很容易插入 id 为 0 值, 现在,当您再次尝试插入值时,因为没有 id 生成器策略,然后 jvm 再次将 id 默认值设置为 0,当休眠尝试使用 id 0 值插入它时,它会抛出 ConstraintViolationException 异常,因为 id 为 0值已存在于数据库中。 因此,如果您想休眠并自动为您的实体分配 ID,您可以使用 jpa 特定的 @GeneratedValue 策略(AUTO/IDENTITY/SEQUENCE/TABLE) 或其他将为实体分配 id 的休眠策略

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

    【讨论】:

    • Bhushan 那么这是什么意思呢? “默认情况下,Id 注释将自动确定要使用的最合适的主键生成策略——您可以通过应用 GeneratedValue 注释来覆盖它。”我需要每次都覆盖策略吗?
    • @Steve,正如我在您刚刚使用 @Id 时提到的,然后使用分配的策略意味着您将负责为您的实体分配 id 而不是休眠。也请你简单介绍一下I need to override the strategy every time?是什么意思
    • @Steve @Id 只指定实体的主键,不负责自动分配id的值,如果你用在@Id上,默认@Id注解会自动确定assigned strategy 意味着应用程序将在调用 save() 或 persist() 之前为对象分配一个标识符(id 值)(意味着您将编写代码,在实体保存之前分配 id 的值)。因此,如果您需要自动生成的 Id 值,那么您需要使用 @GeneratedValue 或其他休眠生成器策略来处理自动分配 id 的值
    • 现在 m 使用@GeneratedValue(strategy = GenerationType.AUTO)on id 字段,代码工作正常。但是我尝试在另一台机器上使用相同的代码,我得到了异常跟踪。 Caused by: java.sql.SQLSyntaxErrorException: ORA-02289: sequence does not exist。这是与数据库相关的问题吗
    • 看起来是oracle db问题,你应该创建一个序列(我们称之为VEHICLE_SEQ)。然后你应该把这个注释放在你的id上:在你的java代码中:@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ") @SequenceGenerator(name = "SEQ", sequenceName = "VEHICLE_SEQ")在db中创建序列:CREATE SEQUENCE VEHICLE_SEQ START WITH 1 INCREMENT BY 1;
    猜你喜欢
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-06
    • 1970-01-01
    • 2016-07-16
    • 2013-01-12
    • 2019-01-27
    相关资源
    最近更新 更多