Fórum Hibernate: definindo uma foreing key com valor null #421579
14/08/2012
0
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
Curtir tópico
+ 0Post mais votado
16/08/2012
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
Davi Costa
Gostei + 1
Mais Posts
14/08/2012
Davi Costa
att Davi
Gostei + 0
14/08/2012
Renan Dantas
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
14/08/2012
Robson Teixeira
Gostei + 0
16/08/2012
Renan Dantas
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
16/08/2012
Davi Costa
Sucesso, precisando é só postar aqui.
att Davi
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)