Classe mapeada no hibernate com chave estrangeira opcional

Boa Tarde.

Gostaria de saber se é possível salvar ou da um merge em um Objeto no hibernate, onde uma coluna na minha tabela é chave estrangeira, mas esta é opcional, logo o usuario não precisa preencher. Nos meus testes o hibernate salva e faz merge se estes campos estão preenchidos, mas se algum destes campo está vazio ele acusa o seguinte erro:

16:28:13,338 INFO [STDOUT] 16:28:13,338 ERROR [GenericDao] [SalvaPojo] object references an unsaved transient instance - save the transient instance before flushing: brd.sinfam.entidade.NotificacaoAmbiental

Vale lembrar que o objeto está com o construtor default, logo vazio, se eu seto o mesmo como null ele salva e faz merge, mas se o usuario atualiza esse campo nulo e adiciona um valor que existe na tabela, ele nao faz o merge.

package brd.sinfam.entidade;

import java.io.Serializable;
import java.math.BigDecimal;
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.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;


@NamedQueries({
	@NamedQuery(name="buscaPorNumeroAIA", query="SELECT A FROM AutoInfracaoAmbiental A WHERE A.autoInfracaoAmbientalNumero = :numero")
})
@Entity
@Table(name="auto_infracao")
@SequenceGenerator(name="seq_auto_infracao", sequenceName="seq_auto_infracao")
public class AutoInfracaoAmbiental implements Serializable{

	private static final long serialVersionUID = 1L;
	
	@Id
	@GeneratedValue(generator="seq_auto_infracao")
	@Column(name="autin_codigo", nullable=false)
	private Integer autoInfracaoAmbientalCodigo;
	
	@OneToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="docto_codigo")
	private Documento autoInfracaoAmbientalDocumento;
	
	@Column(name="autin_numero", nullable=false)
	private Integer autoInfracaoAmbientalNumero;
	
	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="autin_autuado", nullable=false)
	private Pessoa autoInfracaoAmbientalAutuado;
	
	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="end_codigo", nullable=false)
	private Endereco autoInfracaoAmbientalEndereco;
	
	@Temporal(TemporalType.DATE)
	@Column(name="autin_data_infracao", nullable=false)
	private Date autoInfracaoAmbientalDataInfracao;
	
	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="cafis_codigo", nullable=false)
	private CategoriaFiscalizacao autoInfracaoAmbientalCategoriaFiscalizacao;
	
	@Column(name="autin_indicativo_multa_inicial", nullable=false, precision=2)
	private BigDecimal autoInfracaoAmbientalMultaInicial;
	
	@Column(name="autin_indicativo_multa_final", nullable=false, precision=2)
	private BigDecimal autoInfracaoAmbientalMultaFinal;
	
	@Column(name="autin_descricao", nullable=false)
	private String autoInfracaoAmbientalDescricao;
	
	@ManyToOne(fetch=FetchType.EAGER, optional=true)
	@JoinColumn(name="notam_codigo", nullable=true)
	private NotificacaoAmbiental autoInfracaoAmbientalNotificacaoAmbiental;
	
	@Column(name="autin_aia_codigo")
	private Integer autoInfracaoAmbientalCodigoNNA;
	
	@Temporal(TemporalType.DATE)
	@Column(name="autin_data_recebimento", nullable=false)
	private Date autoInfracaoAmbientalDataRecebimento;
	
	@OneToOne(fetch=FetchType.EAGER, optional=true)
	@JoinColumn(name="autin_subtituido_por", referencedColumnName="autin_codigo", nullable=true)
	private AutoInfracaoAmbiental autoInfracaoAmbientalSubstituicao;
	
	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="autin_autuado_preposto", nullable=false)
	private Pessoa autoInfracaoAmbientalAutuadoPreposto;
	
	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="autin_testemunha1", nullable=false)
	private Pessoa autoInfracaoAmbientalTestemunha1;
	
	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="autin_testemunha2", nullable=false)
	private Pessoa autoInfracaoAmbientalTestemunha2;
	
	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="autin_agente_fiscal", nullable=false)
	private Pessoa autoInfracaoAmbientalAgenteFiscal;
	
	@OneToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="procf_codigo", nullable=true)
	private ProcessoFiscalizacao autoInfracaoAmbientalProcessoFiscalizacao;
	
	@Column(name="autin_observacao")
	private String autoInfracaoAmbientalObservacao;
	
	@ManyToMany(fetch=FetchType.EAGER,cascade={CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE})
	@JoinTable(name="documento_enquadramento", 
				joinColumns={@JoinColumn(name="docto_codigo", nullable=false, referencedColumnName="docto_codigo")}, 
				inverseJoinColumns={@JoinColumn(name="enqua_codigo", nullable=false)})
	private List<Enquadramento> autoInfracaoAmbientalEnquadramentos;
	

	public AutoInfracaoAmbiental() {
		autoInfracaoAmbientalDocumento = new Documento();
		autoInfracaoAmbientalAutuado = new Pessoa();
		autoInfracaoAmbientalEndereco = new Endereco();
		autoInfracaoAmbientalCategoriaFiscalizacao = new CategoriaFiscalizacao();
		autoInfracaoAmbientalNotificacaoAmbiental = new NotificacaoAmbiental();
		autoInfracaoAmbientalAutuadoPreposto = new Pessoa();
		autoInfracaoAmbientalTestemunha1 = new Pessoa();
		autoInfracaoAmbientalTestemunha2 = new Pessoa();
		autoInfracaoAmbientalAgenteFiscal = new Pessoa();
		autoInfracaoAmbientalProcessoFiscalizacao = new ProcessoFiscalizacao();
		autoInfracaoAmbientalEnquadramentos = new ArrayList<Enquadramento>();
	}

Então é melhor vc fazer um Find no objeto do banco, editar campo a campo, objetoVelho.setNome(objetoNovo.getNome()); e depois mandaro merge.

Vou tentar, qualque coisa eu posto aqui.

So me encomodo com o hibernate, SQL’s nativos facilitam muito mais!!! Mas a empresa usa, já falei que se eu nao der jeito vou fazer na unha essa tarefa :S

Facilitar facilita, mas o problema é que vc está vindo com um objeto que ele não tem conhecimento.

O que vc pode fazer é, na hora q o usuário for colocar o objeto para edição vc coloca a chave lah escondida. aí quando for para edição, seu valor vai estar lah! [=