2016-11-23 3 views
1

Ich habe ein Problem in Bezug auf Ruhezustand und Fremdschlüssel Einschränkungen.Spring Hibernate Forgein Schlüsseleinschränkung

Ich habe das folgende Szenario (Pseudo-Java-Code). Ich habe eine Elternklasse (Abteilung)

@Entity 
public class Department { 

    @Id 
    private Long id; 

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "department", cascade = CascadeType.ALL) 
    List<Person> persons; 

    public void addToPersons(Person p) { 
    if (this.persons == null) { 
     this.persons = new ArrayList<>(); 
    } 
    this.persons.add(p); 
    p.setDepartment(this); 
    } 

    public void setId(Long id) { 
    this.id = id; 
    } 

} 

und ein Kind Klasse (Person)

@Entity 
public class Person { 

    @Id 
    private String name; 

    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
    private List<Person> followers; 

    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "followers") 
    private List<Person> following; 

    @ManyToOne(fetch = FetchType.LAZY) 
    private Department department; 

    public void addToFollowers(Person p) { 
    if (this.followers == null) { 
     this.followers = new ArrayList<>(); 
    } 
    if (!this.followers.contains(p)) { 
     this.followers.add(p); 
    } 
    } 

    public void addToFollowing(Person p) { 
    if (this.following == null) { 
     this.following = new ArrayList<>(); 
    } 
    if (!this.following.contains(p)) { 
     this.following.add(p); 
    } 
    } 

    public void setDepartment(Department department) { 
    this.department = department; 
    } 

    public void setName(String name) { 
    this.name = name; 
    } 

    @Override 
    public boolean equals(Object o) { 
    if (this == o) return true; 
    if (o == null || getClass() != o.getClass()) return false; 
    Person that = (Person) o; 
    return name != null ? name.equals(that.name) : that.name == null; 
    } 

} 

Zur Vervollständigung, die Repository-Klasse

public interface DepartmentRepository extends CrudRepository<Department, Long> {} 

Der Controller, der die Ausnahme verursacht

@RestController 
public class MainController { 

    @Autowired 
    private DepartmentRepository departmentRepository; 

    @RequestMapping("/") 
    @ResponseBody 
    public String index() { 
    Department d1 = new Department(); 
    d1.setId(1L); 

    Department d2 = new Department(); 
    d2.setId(2L); 

    Person john = new Person(); 
    john.setName("John"); 

    Person alice = new Person(); 
    alice.setName("Alice"); 

    john.addToFollowers(alice); 
    alice.addToFollowing(john); 

    d1.addToPersons(john); 
    d2.addToPersons(alice); 

    departmentRepository.save(d1); // <-- throws violation exception 

    return "foo"; 
    } 

} 

Ich denke es wirft die Ausnahme wegen Verletzung, weil die Abteilung d2 noch nicht gespeichert wurde, aber ist es möglich, dies zu tun, ohne vorher alle Entitäten explizit zu speichern ?!

Danke!

UPDATE

den Code abgeschlossen. Die Ausnahme Ursache:

2016-11-24 11:45:40.513 ERROR 19927 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : INSERT on table 'PERSON' caused a violation of foreign key constraint 'FK_R2AEQQXC7UWBN48SHRHMAI8CX' for key (2). The statement has been rolled back. 
2016-11-24 11:45:40.514 INFO 19927 --- [nio-8080-exec-1] o.h.e.j.b.internal.AbstractBatchImpl  : HHH000010: On release of batch it still contained JDBC statements 
2016-11-24 11:45:40.526 ERROR 19927 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause 

org.apache.derby.iapi.error.StandardException: INSERT on table 'PERSON' caused a violation of foreign key constraint 'FK_R2AEQQXC7UWBN48SHRHMAI8CX' for key (2). The statement has been rolled back. 
at org.apache.derby.iapi.error.StandardException.newException(Unknown Source) ~[derby-10.12.1.1.jar:na] 
at org.apache.derby.iapi.error.StandardException.newException(Unknown Source) ~[derby-10.12.1.1.jar:na] 
at org.apache.derby.impl.sql.execute.ForeignKeyRIChecker.doCheck(Unknown Source) ~[derby-10.12.1.1.jar:na] 
at org.apache.derby.impl.sql.execute.RISetChecker.doFKCheck(Unknown Source) ~[derby-10.12.1.1.jar:na] 
at org.apache.derby.impl.sql.execute.InsertResultSet.normalInsertCore(Unknown Source) ~[derby-10.12.1.1.jar:na] 
at org.apache.derby.impl.sql.execute.InsertResultSet.open(Unknown Source) ~[derby-10.12.1.1.jar:na] 
at org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(Unknown Source) ~[derby-10.12.1.1.jar:na] 
at org.apache.derby.impl.sql.GenericPreparedStatement.execute(Unknown Source) ~[derby-10.12.1.1.jar:na] 
at org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(Unknown Source) ~[derby-10.12.1.1.jar:na] 
at org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeStatement(Unknown Source) ~[derby-10.12.1.1.jar:na] 
at org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeLargeUpdate(Unknown Source) ~[derby-10.12.1.1.jar:na] 
at org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeUpdate(Unknown Source) ~[derby-10.12.1.1.jar:na] 
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:62) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3124) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3581) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:104) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:465) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:351) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1258) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final] 
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517) ~[spring-orm-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761) ~[spring-tx-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730) ~[spring-tx-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:485) ~[spring-tx-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291) ~[spring-tx-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ~[spring-tx-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:131) ~[spring-data-jpa-1.9.1.RELEASE.jar:na] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at com.sun.proxy.$Proxy69.save(Unknown Source) ~[na:na] 
at com.ottogroup.test.MainController.index(MainController.java:40) ~[classes/:na] 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_80] 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_80] 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_80] 
at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_80] 
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) ~[tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) ~[tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.0.28.jar:8.0.28] 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217) ~[tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) [tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) [tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) [tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673) [tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500) [tomcat-embed-core-8.0.28.jar:8.0.28] 
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456) [tomcat-embed-core-8.0.28.jar:8.0.28] 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_80] 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_80] 
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.0.28.jar:8.0.28] 
at java.lang.Thread.run(Thread.java:745) [na:1.7.0_80] 
+0

Sie haben keine "Abteilung" hier. Und könnten Sie Methoden und eine vollständige Stack-Trace hinzufügen. –

Antwort

0
@Entity(name = "department")  
class Department { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private int idx 

    @OneToMany(mappedBy = "department", cascade = { CascadeType.ALL }) 
    List<Person> person; 

    // getter, setter... 
} 

@Entity(name = "Person") 
class Person { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private int idx; 

    @ManyToOne 
    @JoinColumn(name = "department_id") 
    private Department department; 

    // getter, setter... 
} 


Department department = new Department(); 
Person p1 = new Person(); 
Person p2 = new Person(); 

p1.setDepartment(department); 
p2.setDepartment(department); 

personRepository.save(p1); 
personRepository.save(p2); 
0

In Ihrer d.addToPersons(p1); Implementierung sicherstellen, dass Sie die Abteilung Person gesetzt als auch,

public void addToPersons(Person person){ 
person.setDepartment(this); 
this.persons.add(person); 
} 

gleiche gilt für andere Beziehungen