Hibernate: definindo uma foreing key com valor null
Bom, a situação é a seguinte:
Tenho uma tabela Pessoa, que tem uma foreign key da tabela Grupo.
Uma Pessoa pode pertencer à 1 Grupo, e 1 Grupo pode ter N Pessoas.
No banco de dados, defini que a FK id_grupo não é NOT NULL, portanto, era
para aceitar um null.
Tudo funciona bunitinho quando adiciono esse Grupo no cadastro da Pessoa.
O problema nasce quando eu tento adicionar uma pessoa sem definir um grupo para ela, eu recebo um erro
dizendo que devo persistir o objeto Grupo antes de referenciá-lo. Mas, eu NÃO quero referenciá-lo, uma vez que
ele é nulo.
O stacktrace é o seguinte:
Já procurei em inúmeros fóruns, e o pessoal insiste em me aconselhar à usar um Cascade, mas isso não faz o menor sentido!
Eu não quero que ele insira no banco o objeto Grupo quando ele for nulo!!!
Será que alguem poderia me dar uma luz??
Tenho uma tabela Pessoa, que tem uma foreign key da tabela Grupo.
Uma Pessoa pode pertencer à 1 Grupo, e 1 Grupo pode ter N Pessoas.
No banco de dados, defini que a FK id_grupo não é NOT NULL, portanto, era
para aceitar um null.
Tudo funciona bunitinho quando adiciono esse Grupo no cadastro da Pessoa.
O problema nasce quando eu tento adicionar uma pessoa sem definir um grupo para ela, eu recebo um erro
dizendo que devo persistir o objeto Grupo antes de referenciá-lo. Mas, eu NÃO quero referenciá-lo, uma vez que
ele é nulo.
O stacktrace é o seguinte:
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.jm.beans.Eleitor
org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:249)
org.hibernate.type.EntityType.getIdentifier(EntityType.java:456)
org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:276)
org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:286)
org.hibernate.type.TypeHelper.findDirty(TypeHelper.java:294)
org.hibernate.persister.entity.AbstractEntityPersister.findDirty(AbstractEntityPersister.java:3820)
org.hibernate.event.internal.DefaultFlushEntityEventListener.dirtyCheck(DefaultFlushEntityEventListener.java:536)
org.hibernate.event.internal.DefaultFlushEntityEventListener.isUpdateNecessary(DefaultFlushEntityEventListener.java:243)
org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:172)
org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:225)
org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1127)
org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:325)
org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
br.com.jm.dao.DemandaDAO.insert(DemandaDAO.java:28)
br.com.jm.factory.DemandaFactory.executeInsert(DemandaFactory.java:30)
br.com.jm.actions.DemandaAction.incluirDemanda(DemandaAction.java:129)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:453)
com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:292)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:255)
org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:176)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)
org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:68)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:211)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:211)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:190)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:90)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:243)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:176)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:192)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:510)
org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:434)
Já procurei em inúmeros fóruns, e o pessoal insiste em me aconselhar à usar um Cascade, mas isso não faz o menor sentido!
Eu não quero que ele insira no banco o objeto Grupo quando ele for nulo!!!
Será que alguem poderia me dar uma luz??
Renan Dantas
Curtidas 0
Melhor post
Davi Costa
16/08/2012
Avaliando com calma seu log:
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.jm.beans.Eleitor
Parace que vc pode ter dado algum new nesse atributo de grupo, no objeto que vc quiz salvar no banco. verifica isso, se for o casobasta colocar null nesse atributo antes de salvar.
att Davi
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.jm.beans.Eleitor
Parace que vc pode ter dado algum new nesse atributo de grupo, no objeto que vc quiz salvar no banco. verifica isso, se for o casobasta colocar null nesse atributo antes de salvar.
att Davi
GOSTEI 1
Mais Respostas
Davi Costa
14/08/2012
posta os dois mapemanetos aqui.Vai ficar mais fácil para te ajudar
att Davi
att Davi
GOSTEI 0
Renan Dantas
14/08/2012
Aqui vão as classes:
Classe Eleitor:
Classe Grupo:
O mesmo acontece com outra classe que tem relacionamento com Eleitor, a classe Demanda.
Nesta classe, é o Eleitor que deveria ser nulo dentro da Demanda, porém, recebo o mesmo stacktrace
ao tentar gravar uma Demanda com uma FK de Eleitor sendo nula.
Classe Demanda:
Dei uma olhada no meu banco, e na tabela Eleitor, a chave extrangeira referente ao Grupo estava com cascade definido como RESTRICT.
Fiz a alteração e vou testar agora, mas não creio que isso irá surtir efeito, uma vez que na tabela Demanda, o cascade está como NO ACTION
e ainda assim tenho o mesmo resultado.
Classe Eleitor:
package br.com.jm.beans;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
@Entity
@Table(name=eleitor)
public class Eleitor implements Serializable{
private static final long serialVersionUID = -6226011868072777381L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name=id_eleitor)
private Integer idEleitor;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name=id_cidade)
private Cidade cidade;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name=id_grupo)
private Grupo grupo;
@Column(name=el_nome)
private String nome;
@Column(name=el_apelido)
private String apelido;
@Column(name=el_sexo)
private String sexo;
@Column(name=el_data_nasc)
@Temporal(TemporalType.DATE)
private Date dataNasc;
//INFINIDADE DE VARIÁVEIS
@ManyToMany(cascade={CascadeType.MERGE,CascadeType.REMOVE},fetch=FetchType.LAZY)
@JoinTable(name=cursos_eleitor,
joinColumns = @JoinColumn(name=id_eleitor, referencedColumnName=id_eleitor),
inverseJoinColumns = @JoinColumn(name=id_curso, referencedColumnName=id_curso))
private ListCurso listaCursos = new ArrayListCurso();
@OneToMany(mappedBy=eleitor, cascade={CascadeType.MERGE,CascadeType.REMOVE},fetch=FetchType.LAZY)
private ListCampanhasEleitor listaCampanhasEleitor = new ArrayListCampanhasEleitor();
@OneToMany(mappedBy=eleitor, cascade={CascadeType.MERGE,CascadeType.REMOVE},fetch=FetchType.LAZY)
private ListExperiencia listaExperiencias = new ArrayListExperiencia();
@OneToMany(mappedBy=eleitor, cascade={CascadeType.MERGE,CascadeType.REMOVE},fetch=FetchType.LAZY)
private ListDemanda listaDemandas = new ArrayListDemanda();
@Transient
private DateFormat sdf = new SimpleDateFormat(dd/MM/yyyy);
@Transient
private DecimalFormat df = new DecimalFormat();
@Transient
private String dia;
@Transient
private String mes;
@Transient
private String ano;
//------------------------Getters e Setters--------------------------------
}
Classe Grupo:
package br.com.jm.beans;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = grupo)
public class Grupo implements Serializable {
private static final long serialVersionUID = -7112823581533993573L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = id_grupo)
private Integer idGrupo;
@Column(name = gp_nome)
private String nome;
public Grupo(){
}
//GETTERS E SETTERS
}
O mesmo acontece com outra classe que tem relacionamento com Eleitor, a classe Demanda.
Nesta classe, é o Eleitor que deveria ser nulo dentro da Demanda, porém, recebo o mesmo stacktrace
ao tentar gravar uma Demanda com uma FK de Eleitor sendo nula.
Classe Demanda:
package br.com.jm.beans;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity
@Table(name=demanda)
public class Demanda implements Serializable{
private static final long serialVersionUID = 4959562413119839409L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name=id_demanda)
private Integer idDemanda;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name=id_eleitor, nullable=true)
private Eleitor eleitor;
@Column(name=dm_solic)
private String solic;
@Column(name=dm_obs)
private String obs;
@Column(name=dm_status)
private String status;
@OneToMany(mappedBy=demanda, fetch=FetchType.EAGER, cascade={CascadeType.DETACH,CascadeType.REMOVE})
private ListOcorrencia listaOcorrencias;
@Transient
private SimpleDateFormat sdf = new SimpleDateFormat(dd/MM/yyyy);
@Transient
private Date periodoIni;
@Transient
private Date periodoFin;
//GETTERS E SETTERS
}
Dei uma olhada no meu banco, e na tabela Eleitor, a chave extrangeira referente ao Grupo estava com cascade definido como RESTRICT.
Fiz a alteração e vou testar agora, mas não creio que isso irá surtir efeito, uma vez que na tabela Demanda, o cascade está como NO ACTION
e ainda assim tenho o mesmo resultado.
GOSTEI 0
Robson Teixeira
14/08/2012
verifique o mapeamento de cascade nas suas classes de entidade, principalmente o cascade e também verifique se não ha atributo com anotação @NotNull ou @NotEmpty.
GOSTEI 0
Renan Dantas
14/08/2012
Davi, acertou em cheio no problema cara!
Só que em momento nenhum eu dei um new nesse objeto. Porém, antes de executar o persist, verifiquei se o objeto era
realmente nulo, ou se era um objeto Grupo com dados nulos, daí funcionou!
Brigadão cara!
Só que em momento nenhum eu dei um new nesse objeto. Porém, antes de executar o persist, verifiquei se o objeto era
realmente nulo, ou se era um objeto Grupo com dados nulos, daí funcionou!
Brigadão cara!
GOSTEI 0
Davi Costa
14/08/2012
Show de bola Renan!
Sucesso, precisando é só postar aqui.
att Davi
Sucesso, precisando é só postar aqui.
att Davi
GOSTEI 0