In my spring appliucation, I am using Hibernate to deal with the operations with the database. Right now, when I try insert a registry in a table with a foreign key, I am getting an error. For instance, the table represented by this entity class:
@Entity
@Table(name="pagina")
public class Pagina extends Entidade {
@Id
@Column(name = "id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer Id;
@Column(name = "nome", unique=true)
private String nome;
@Column(name = "titulo")
private String titulo;
@Column(name = "descricao")
private String descricao;
@OneToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
@JoinColumn(name="parent_page")
@Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
private Pagina pagina;
@OneToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
@JoinColumn(name="parent_product")
@Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
private Produto produto;
}
I have this view to insert data in that table:
<html lang="en">
<head>
<title>Pagina</title>
</head>
<body>
<h1>Cadastro de Pagina</h1>
<form id="command" role="form" class="form" action="Pagina/cadastra" method="post">
<div class="panel panel-default">
<div class="panel-heading">
</div>
<div class="panel-body">
<p>
<label for="nome" class="form-control">nome</label>
<input id="nome" name="nome" class="form-control" type="text" value=""/>
</p>
<p>
<label for="titulo" class="form-control">titulo</label>
<input id="titulo" name="titulo" class="form-control" type="text" value=""/>
</p>
<p>
<label for="descricao" class="form-control">descricao</label>
<textarea id="descricao" name="descricao" class="form-control"></textarea>
</p>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
Pagina
</div>
<div class="panel-body">
<input type="checkbox" name="Pagina.id" value="2">two<br>
<input type="checkbox" name="Pagina.id" value="1">one<br>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
Produto
</div>
<div class="panel-body">
</div>
</div>
<p>
<button type="submit" class="btn btn-lg btn-primary">Cadastrar</button>
</p>
</form>
<div id="yes" class="alert alert-success" style="display: none;">
<strong>Pronto!</strong> Solicitação efetuada com sucesso.
</div>
<div id="not" class="alert alert-danger" style="display: none;">
<strong>Erro!</strong> Não foi possivel efetivar a sua solicitação.
</div>
</body>
</html>
which is handled by this methods:
in the controller class
@RequestMapping(value="cadastra", method=RequestMethod.POST)
@ResponseBody
public String cadastra(@ModelAttribute("object") E object, BindingResult result) {
if(serv.cadastra(object))
return "yes";
else
return "not";
}
in the service class
@PreAuthorize("hasPermission(#user, 'cadastra_'+#this.this.name)")
@Transactional
public boolean cadastra(E e) {
return dao.persist(e);
}
if I try insert a item without select one of the checkboxes, the transaction is executed correctly, but if I mark them, I get the error:
org.hibernate.AssertionFailure: null id in com.spring.loja.model.pagina.persistence.model.Pagina entry (don't flush the Session after an exception occurs)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:77)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:192)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:152)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:231)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:102)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:55)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:555)
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.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
at com.spring.loja.model.pagina.service.PaginaService$$EnhancerBySpringCGLIB$$df6523ad.cadastra(<generated>)
at com.spring.loja.config.generic.controller.controller.cadastra(controller.java:69)
at com.spring.loja.config.generic.controller.controller$$FastClassBySpringCGLIB$$c8cc444b.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:640)
at com.spring.loja.model.pagina.controller.PaginaController$$EnhancerBySpringCGLIB$$3b87d072_2.cadastra(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
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:745)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
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:936)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:838)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
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.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
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.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
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.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
I can't figure out why this happening. Anyone can point me in the right direction to solve this?
UPDATE
I made some modifications in my entity class and try some differents implementations for my Dao class, and still facing errors (but different errors). My entity class is now this:
@Entity
@Table(name="pagina")
public class Pagina extends Entidade {
@Id
@Column(name = "id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer Id;
@Column(name = "nome", unique=true)
private String nome;
@Column(name = "titulo")
private String titulo;
@Column(name = "descricao")
private String descricao;
@OneToOne( cascade = {CascadeType.ALL}, fetch = FetchType.EAGER )
@JoinColumn(name="parent_page")
@Cascade(org.hibernate.annotations.CascadeType.ALL)
private Pagina pagina;
@OneToOne( cascade = {CascadeType.ALL}, fetch = FetchType.EAGER )
@JoinColumn(name="parent_product")
@Cascade(org.hibernate.annotations.CascadeType.ALL)
private Produto produto;
}
In my Dao class, I try this two implementations for my method persist(...)
:
@Transactional
public boolean persist(E transientInstance) {
try {
sessionFactory.getCurrentSession().persist(transientInstance);
return true;
} catch (RuntimeException e) {
e.printStackTrace();
return false;
}
}
and
@Transactional
public boolean persist(E transientInstance) {
try {
sessionFactory.getCurrentSession().save(transientInstance);
return true;
} catch (RuntimeException e) {
e.printStackTrace();
return false;
}
}
with both options, if I try save an entity without no atribute Pagina or Produto, it's stored in the database with no problems. But if I try submit data with this atributes, I face problems.
with the first option, an exception org.hibernate.PersistentObjectException: detached entity passed to persist
is triggered, and with the second option, the data is stored in the database, but with error, since a extra row with no values are stored in the database, and the line with the data I inserted points to that line.
Anyone knows what's happening here? Because I have no clue.