Здравствуйте, помогите разобраться с проблемой.
Есть структура данных, которая представляет своего рода граф объектов, и надо эту структуру данных сохранить в БД.
Данные представлены след. классами:
Код |
@Entity public class SimObj { @Id @GeneratedValue(strategy = GenerationType.TABLE) private Long id;
//....
@LazyCollection(LazyCollectionOption.FALSE) @OneToMany(cascade = CascadeType.ALL) private List<SimObjField> simFields; @LazyCollection(LazyCollectionOption.FALSE) @OneToMany(cascade = CascadeType.ALL) private List<SimObjListField> simListFields; }
@Entity public class SimObjField implements IField<SimObj>{ @Id @GeneratedValue(strategy = GenerationType.TABLE) private Long id;
private String name;
@OneToOne(cascade=CascadeType.ALL) private SimObj value; }
@Entity public class SimObjListField implements IField<List<SimObj>>{ @Id @GeneratedValue(strategy = GenerationType.TABLE) private Long id;
private String name; @LazyCollection(LazyCollectionOption.FALSE) @OneToMany(cascade = CascadeType.ALL) private List<SimObj> simList; }
|
Причем граф имеет циклы, т.е. имеются связи вида: simObj #1 -> simField #1 -> simObj #2 -> simField#2 -> simObj #1. Также бывает, что simObj #1 ссылается на simObj #2 несколько раз.
Т.е одновременно существуют связи:
simObj #1 -> simField #1(имя: parent) -> simObj #2
simObj #1 -> simField #3(имя: sector) -> simObj #2
Тестирование происходит след. образом:
Генерируется граф объектов, причем всегда есть своего рода корневой узел, от которого существует путь до любого другого узла.
Далее этот корневой узел сохранятся в БД c использованием spring и hibernate таким образом:
Код |
@Transactional public Long save(SimObj anElement) throws DAOException,IllegalArgumentException { Session session = getSession(); //hibernate session return (Long) session.save(anElement); }
|
И при попытке сохранения возникает ошибка:
Код |
org.springframework.dao.DataIntegrityViolationException: could not insert collection: [org.stl.optimus.db.persist.SimObjListField.simList#2]; SQL [insert into SimObjListField_SimObj (SimObjListField_id, simList_id) values (?, ?)]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not insert collection: [org.stl.optimus.db.persist.SimObjListField.simList#2] at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:637) at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793) at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723) at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) at $Proxy21.save(Unknown Source) at org.stl.optimus.tests.db.SaveSpaceTest.test(SaveSpaceTest.java:59) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59) at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98) at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79) at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87) at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77) at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42) at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88) at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51) at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44) at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27) at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37) at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: org.hibernate.exception.ConstraintViolationException: could not insert collection: [org.stl.optimus.db.persist.SimObjListField.simList#2] at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1243) at org.hibernate.action.CollectionRecreateAction.execute(CollectionRecreateAction.java:58) at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:188) at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216) at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383) at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133) at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656) ... 30 more Caused by: java.sql.BatchUpdateException: Duplicate entry '6' for key 'simList_id' at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2018) at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1449) at com.p6spy.engine.logging.P6LogPreparedStatement.executeBatch(P6LogPreparedStatement.java:329) at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) at org.hibernate.jdbc.BatchingBatcher.addToBatch(BatchingBatcher.java:56) at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1206) ... 40 more
|
База перед сохранением данных пуста.
В одной транзакции сохраняется примерно 3500 объектов. Когда экспериментировал с небольшим числом объектов(около 10) таких проблем не возникало
Копание интернетов результата не принесло. Пробовал менять алгоритмы генерации ID - тоже не помогло.
Вопрос: можно ли в принципе сохранять такие данные? и как найти проблемное место?
P.S. методы equals() и hashCode не переопределял.