J'ai une entité:
@Entity
public class Student {
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private long id;
@OneToMany
private Set<Course> courses;
}
Lorsque j'essaie de conserver la première entité de ce type, cela fonctionne correctement, mais lorsque j'essaie de sauvegarder un nouvel étudiant avec le même cours que l'entité déjà stockée, il échoue. Voici l'erreur:
insert into student_courses (student, courses) values (?, ?) [23505-172]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "UK_1DBE7B943AC44E1B841DA2688EB_INDEX_5 ON PUBLIC.STUDENT_COURSES(COURSES)"; SQL statement:
insert into student_courses (student, courses) values (?, ?) [23505-172]
at org.h2.message.DbException.getJdbcSQLException(DbException.Java:329)
at org.h2.message.DbException.get(DbException.Java:169)
at org.h2.message.DbException.get(DbException.Java:146)
at org.h2.index.BaseIndex.getDuplicateKeyException(BaseIndex.Java:83)
at org.h2.index.TreeIndex.add(TreeIndex.Java:65)
at org.h2.table.RegularTable.addRow(RegularTable.Java:124)
at org.h2.command.dml.Insert.insertRows(Insert.Java:126)
at org.h2.command.dml.Insert.update(Insert.Java:86)
at org.h2.command.CommandContainer.update(CommandContainer.Java:79)
at org.h2.command.Command.executeUpdate(Command.Java:235)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.Java:154)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.Java:140)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.Java:133)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.Java:58)
at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.Java:1256)
at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.Java:58)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.Java:364)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.Java:356)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.Java:281)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.Java:328)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.Java:52)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.Java:1234)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.Java:404)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.Java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.Java:175)
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.Java:75)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.Java:515)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.Java:757)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.Java:726)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.Java:478)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.Java:272)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.Java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.Java:158)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:179)
at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.Java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.Java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.Java:207)
at com.Sun.proxy.$Proxy45.save(Unknown Source)
at students.StudentController.createRandomShiur(ShiurimController.Java:66)
at shiurim.StudentController.getStudents(StudentController.Java:26)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:39)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:25)
at Java.lang.reflect.Method.invoke(Method.Java:597)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.Java:220)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.Java:133)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.Java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.Java:746)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.Java:687)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.Java:83)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.Java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.Java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:946)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.Java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.Java:621)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.Java:822)
at javax.servlet.http.HttpServlet.service(HttpServlet.Java:728)
at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:305)
at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.Java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:108)
at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:222)
at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:123)
at org.Apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.Java:502)
at org.Apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.Java:680)
at org.Apache.catalina.core.StandardHostValve.invoke(StandardHostValve.Java:171)
at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:99)
at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:118)
at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:408)
at org.Apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.Java:1023)
at org.Apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.Java:589)
at org.Apache.Tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.Java:1686)
at Java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.Java:895)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:918)
at Java.lang.Thread.run(Thread.Java:695)
J'utilise Spring Data JPA avec Hibernate et H2 comme base de données.
L'application a créé ses propres tables de base de données:
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setShowSql(false);
hibernateJpaVendorAdapter.setGenerateDdl(true);
hibernateJpaVendorAdapter.setDatabase(Database.H2);
Alors, pourquoi y aurait-il une contrainte unique?
Mettre à jour:
Je vois que Hibernate a ajouté la contrainte:
Hibernate: alter table student_courses add constraint UK_a8c48f36df374f1293c46699c83 unique (courses)
Comment puis-je dire à Hibernate de ne pas créer cela?
Merci!
Étant donné que la violation se produit dans la table STUDENT_COURSES
, il semble que vous tentiez de conserver deux fois la même relation. Vous avez mappé une Set
, qui indique à Hibernate que ces relations ne doivent pas se produire plus d'une fois. Recherchez dans le DDL généré des index uniques sur COURSE_ID, STUDENT_ID).
La raison peut être une faille dans la logique de votre programme (par exemple, la modification de champs pertinents pour equals
sur Course
s après leur ajout à l'ensemble ou un equals
défectueux dans votre entité Course
.
Vous devez décider vous-même (votre client dans le monde réel, puisqu'il s'agit d'une décision commerciale), si un Student
peut participer à un Course
plusieurs fois (par exemple, il a échoué la première fois).
Ce n'est pas le problème avec Sequence/JPA /hibern.Selon votre journal, l'erreur est survenue sur student_courses
insert into student_courses
UK_1DBE7B943AC44E1B841DA2688EB_INDEX_5
Il semble que vous ayez une contrainte unique dans la table student_course avec des cours. supprimez cette contrainte unquie/vous devrez peut-être ajouter un composite d'étudiant et de cours pour la contrainte unquie et pas seulement les cours.
Vous devez utiliser GenerationType.TABLE
au lieu de GenerationType.AUTO
. De cette façon, jpa utilise une table de séquence pour l'attribution d'identifiant et vous n'aurez peut-être jamais besoin de générer de valeur de séquence ou d'incrémentation automatique ni de déclencheurs réduisant la portabilité.