Problema ao persistir em cascata

12 respostas
D

Pessoal …

Tenho uma entidade denominada Empresa e uma entidade Enderecos e uma relação 1…N na mesma, efetuei o seguinte mapeamento.

Na entidade Empresa

@OneToMany(cascade = CascadeType.ALL, mappedBy = "empresa")
@ForeignKey(name = "fk_end_emp")
private Collection<Endereco> enderecos;

Na entidade endereços

@ManyToOne(fetch=FetchType.LAZY,cascade = CascadeType.ALL)
@ForeignKey(name="fk_end_emp")
@JoinColumn(name = "empresa_id", referencedColumnName="id", nullable = false)
private Empresa empresa;

Como não estava dando certo fui debugando passo a passo e antes de salvar o objeto está populado tenho um objeto empresa todo populado e dentro dele um objeto endereço populado também, e só recebo esta stack

Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value: br.com.saf.entities.Endereco.empresa
        at org.hibernate.engine.Nullability.checkNullability(Nullability.java:72)
        at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:290)
        at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
        at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107)
        at org.hibernate.ejb.event.EJB3MergeEventListener.saveWithGeneratedId(EJB3MergeEventListener.java:43)
        at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:186)
        at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:123)
        at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:687)
        at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:669)
        at org.hibernate.engine.CascadingAction$6.cascade(CascadingAction.java:245)
        at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
        at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
        at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
        at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
        at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
        at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
        at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
        at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
        at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:456)
        at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:194)
        at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:123)
        at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:53)
        at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:677)
        at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:661)
        at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:665)

Alguem poderia ajudar?

Muito Obrigado

12 Respostas

D

Acabo de efetuar um teste tirar o " nullable = false" da empresa e ao salvar é salvo todos os dados, tanto da empresa como do endereço porém ele não salva o id da empresa que está sendo inserida no momento.

Se alguem tiver uma dica será bem vinda! =]

B

Muito estranho este erro, tem certeza que os dados estão populados ? Além disso esse é um típico erro de persistir um relacionamento só que sem o cascade, vc tbm poderia verificar se a versão dos seus .class estão corretas no seu servidor…

A

Cara eu estava tendo esse mesmo problema e resolvi assim:

@OneToMany(fetch = FetchType.LAZY, mappedBy = "pessoa")
private Set<ParteProcesso> parteProcessos = new HashSet<ParteProcesso>();
@ManyToOne(targetEntity=Pessoa.class, fetch=FetchType.LAZY)
@JoinColumn(name="ID_PESSOA", nullable=false)
@NotNull
private Pessoa pessoa;
D

Vou efetuar o teste hoje a noite e posto o resultado!

Muito Obrigado pelas colaborações!

D

Eu fiz o teste e não funcionou… agora analisando melhor o log do tomcat quando vou subir a aplicação estou tente este problema que acredito estar totalmente relacionado.

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.MappingException: Unable to find column with logical name: ïd in org.hibernate.mapping.Table(empresa) and its related supertables and secondary tables

Alguem tem algum palpite?

[]'s

B

Poste suas entidades inteiras…

D
@Entity
@Table(name = "empresa")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "indicador")
public class Empresa implements Serializable {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "nome_fantasia", length = 150, nullable = false)
    private String nomeFantasia;

    @Column(name = "razao_social", length = 150, nullable = false)
    private String razaoSocial;

    @Column(name = "mnemonico", length = 20)
    private String mnemonico;

    @Column(name = "telefone", length = 13)
    private String telefone;

    @Column(name = "email", length = 100)
    private String email;

    @Column(name = "cnpj", length = 18, nullable = false)
    private String cnpj;

    @Column(name = "ie", length = 18, nullable = false)
    private String ie;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "empresa", cascade=CascadeType.ALL)
    @ForeignKey(name = "fk_end_emp")
    private Collection<Endereco> enderecos = new ArrayList<Endereco>();

package br.com.saf.entities;

import java.io.Serializable;
import javax.persistence.*;
import org.hibernate.annotations.ForeignKey;

@Entity
@Table(name = "endereco")
public class Endereco implements Serializable {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "logradouro")
    private String logradouro;

    @Column(name = "bairro")
    private String bairro;

    @Column(name = "cidade")
    private String cidade;

    @Column(name = "estado")
    private String estado;

    @Column(name = "cep")
    private String cep;

    @Column(name = "numero")
    private String numero;

    @ManyToOne(targetEntity=Empresa.class, fetch=FetchType.LAZY, cascade=CascadeType.ALL)
    @ForeignKey(name="fk_end_emp")
    @JoinColumn(name = "empresa_id")
    private Empresa empresa;

@Entity
@Table(name = "unidade")
@ForeignKey(name="fk_un_emp")
@DiscriminatorValue(value = "U")
public class Unidade extends Empresa implements Serializable {

    @OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST},
    mappedBy = "unidade")
    private Collection<Usuario> usuarios;

Postei também a Classe Unidade, pois a classe Empresa é abstrata.

B

Já deu para ver um errinho…Para utilizar discriminadores a estratégia é SINGLE_TABLE e não JOINED… Altera isto e tente subir sua aplicação de novo…

D

Obrigado pela dica …

Acabei de fazer o teste, fiz um novo deploy e na hora de subir o projeto ainda tenho este stack …
Ja conferi tudo muitas vezes e nao consigo achar o problema, sera que pode algo com o spring + JPA … para outras tabelas que nao extendem uma tabela abstrata esta tudo normal.

Segue o stack na hora de subir o projeto …

Exception: Unable to find column with logical name: ïd in org.hibernate.mapping.Table(empresa) and its related supertables and secondary tables
        at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessAfterInstantiation(PersistenceAnnotationBeanPostProcessor.java:311)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:959)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:472)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:729)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:381)
        at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255)
        at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
        at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
        at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3934)
        at org.apache.catalina.core.StandardContext.start(StandardContext.java:4429)
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:526)
        at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:630)
        at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:556)
        at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:491)
        at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1206)
        at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:314)
        at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
        at org.apache.catalina.core.StandardHost.start(StandardHost.java:722)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
        at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
        at org.apache.catalina.core.StandardService.start(StandardService.java:516)
        at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:583)
        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.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.MappingException: Unable to find column with logical name: ïd in org.hibernate.mapping.Table(empresa) and its related supertables and secondary tables
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1337)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:308)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:297)
        at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:224)
        at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:503)
        at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:473)
        at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:598)
        at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:569)
        at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:180)
        at org.springframework.beans.factory.annotation.InjectionMetadata.injectFields(InjectionMetadata.java:105)
        at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessAfterInstantiation(PersistenceAnnotationBeanPostProcessor.java:308)
        ... 40 more
Caused by: org.hibernate.MappingException: Unable to find column with logical name: ïd in org.hibernate.mapping.Table(empresa) and its related supertables and secondary tables
        at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:395)
        at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:102)
        at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:88)
        at org.hibernate.cfg.AnnotationConfiguration.processFkSecondPassInOrder(AnnotationConfiguration.java:499)
        at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:304)
        at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1115)
        at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1225)
        at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:159)
        at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:854)
        at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:425)
        at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:131)
        at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:224)
        at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:291)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1368)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1334)
        ... 59 more
B

Acho que não tem muito haver com o Spring não, e JPA suporta mapeamento de herança normalmente, tanto de classes concretas como abstratas…

Me parece algum problema com seus mapeamentos mesmo, eu daria uma simplificada neles, tem alguns redundantes… Tais como @JoinColumn junto com @ForeignKey(Acho preferível utilizar apenas o @JoinColumn), @Column com o mesmo nome do atributo, e na sua chave primária eu mudaria a estratégia para AUTO ao invés de IDENTITY(é mais utilizado com SQL Server) …

Em relação a stack trace o que da para entender é que o Hibernate não encontrou uma coluna com o nome id na tabela Empresa do seu banco, vc podia conferir isto tbm…

Faça essas verificações e tente de novo…As vezes é meio chato achar um erro destes…

Abraços…

D

Farei os testes hoje a noite e posto o resultado!

D

Fiz os testes e por enquanto nada…
O nome das colunas estão todos mapeados corretamente nas classes de acordo com o banco, estou usando o Hibernate pra exportar o schema do banco.
Está bem difícil encontrar o problema, assim que eu tiver uma novidade posto aqui!

[]'s

Criado 11 de março de 2010
Ultima resposta 15 de mar. de 2010
Respostas 12
Participantes 3