我正在从this book学习休眠,我正在尝试保存实体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.Below是异常跟踪。
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时。这种情况对我没有意义。我错过了什么或者是否有任何特定于数据库的问题?
CREATE TABLE BOOK(
ID INTEGER,
NAME VARCHAR2(50)
);
ALTER TABLE BOOK ADD PRIMARY KEY(ID);
答案 0 :(得分:1)
如果没有元素,Hibernate使用分配作为默认生成器策略。在这种情况下,您的应用程序会分配实体的ID。 如果你想hibernate将负责自动生成id,那么你应该使用GeneratedValue或任何其他id生成策略
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
here是一些例子
你的id类型是int
private int id;
当你第一次插入值时,jvm将分配id默认值0,所以hibernate很容易插入id为0的值, 现在当你再次尝试插入值因为没有id生成器策略然后再次jvm设置id默认值0并且当hibernate尝试插入id为0的值然后它抛出 ConstraintViolationException 异常,因为id为0值已存在于数据库中。 因此,如果您希望hibernate自动为您的实体分配Id,您可以使用jpa特定的@GeneratedValue策略(AUTO / IDENTITY / SEQUENCE / TABLE) 或另一个hibernate策略,它将负责为实体分配id
increment
sequence
hilo
native
identity
seqhilo
uuid
guid
select
foreign
sequence-identity