私はエンティティを持っています:
@Entity
public class Student {
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private long id;
@OneToMany
private Set<Course> courses;
}
このタイプの最初のエンティティを永続化しようとすると正常に機能しますが、すでに保存されているエンティティと同じコースで新しい生徒を保存しようとすると失敗します。ここにエラーがあります:
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)
データベースとしてHibernateとH2を備えたSpring Data JPAを使用しています。
アプリケーションは独自のデータベーステーブルを作成しました。
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setShowSql(false);
hibernateJpaVendorAdapter.setGenerateDdl(true);
hibernateJpaVendorAdapter.setDatabase(Database.H2);
では、なぜ固有の制約があるのでしょうか?
更新:
Hibernateが制約を追加したことがわかります。
Hibernate: alter table student_courses add constraint UK_a8c48f36df374f1293c46699c83 unique (courses)
Hibernateにそれを作成しないように指示するにはどうすればよいですか?
ありがとう!
違反はSTUDENT_COURSES
テーブル、同じ関係を2度持続しようとしているようです。 Set
をマップしました。これは、これらの関係が1回だけ発生する必要があることをHibernateに通知します。生成されたDDLでCOURSE_ID、STUDENT_IDの一意のインデックスを確認します。
理由は、プログラムロジックの欠陥(たとえば、equals
に関連するフィールドをセットに追加した後にCourse
に関連するフィールドを変更するか、equals
エンティティの誤ったCourse
にある可能性があります。
Student
がCourse
に複数回参加できる場合(例:初めて失敗した場合)は、自分自身(実際のクライアントはビジネス上の決定であるため)を決定する必要があります。
Sequence/JPA/hibernの問題ではありません。ログによると、student_coursesでエラーが発生しました
insert into student_courses
UK_1DBE7B943AC44E1B841DA2688EB_INDEX_5
コースがあると、student_courseテーブルにunquie制約があるようです。その不穏な制約を削除します。コースだけでなく、不穏な制約のために学生とコースの複合を追加する必要がある場合があります。
GenerationType.TABLE
の代わりにGenerationType.AUTO
を使用する必要があります。そうすることで、JPAはIDの割り当てにシーケンステーブルを使用するため、シーケンス値や自動インクリメント値、または移植性を低下させるトリガーを生成する必要がなくなる場合があります。
@OneToMany
実際に@ManyToMany
関係。
Course
に自動生成されたIDがないと仮定すると、2人目の生徒が同じ名前のコースを追加するとすぐに問題が発生します。
1対多の関係であるため、同じ一意の制限付きIDで新しいコースが作成されます