Jpa cascade all and join column

11 respostas
L

tenho o seguinte cenario, Uma entidade com uma lista de outra mapeada assim:

@OneToMany(cascade =  CascadeType.ALL)
	@JoinColumn(name = "trn_id")
	@ForeignKey(name = "sns_tre_vtr_id_fk")
	public List<VersaoTreinamento> getVersoesTreinamento() {
		return versoesTreinamento;
	}

e um metodo salvar da seguinte maneira:

List<VersaoTreinamento> versoes = getVersoesTreinamento(documentosNormativosNecessarios);
		Treinamento treinamento = new Treinamento();
		treinamento
				.setRegistroCriacao(RegistroCriacaoUtil.getRegistroCriacao());
		treinamento.setUsuarioSns(new UsuarioSns(chaveUsuario));
		treinamento.setVersoesTreinamento(versoes);
		try {
			genericDao.save(treinamento);
		} catch (DaoException e) {
			e.printStackTrace();
		}

porem qdo salvo ele nao grava o id da entidade treinamento na coluna trn_id da
tabela de versaoTreinamento, é algum problema com o cascade?
Uso jpa.

11 Respostas

R

Pra mim parece correto, afinal você está invocando o método save que imagino que seja equivalente a um persist.

Se você estivesse invocando merge aí sim acredito que as entidades da lista seriam alteradas.

(Estou pensando tudo na teoria, não testei essas coisas, mas você pode testar)

L

Testei em debug e verifiquei que estou chamando o persist do entityManager
e tbm verifiquei que no sql gerado pelo jpa nao tem a coluna trn_id do relacionamento
vejam o sql gerado

insert into sns_versao_treinamento (rgc_id, ver_id, vtr_isTreinado) values (?, ?, ?)

o que pode esta ocasionando isso?
obrigado.

L

Ja tentei de varias maneiras e nunca salva o id do treinamento na tabela de versaoTreinamento.
Mesmo qdo salvo separadamente.

E

lgGodoy,

Nos relacionamentos OneToMany, você deve usar o relacionamento bi-direcional, ou seja, mapear os relacionamentos nas duas entidades.
//Entidade treinamento
    @OneToMany(mappedBy = "treinamento", cascade =  CascadeType.ALL)  
    @ForeignKey(name = "sns_tre_vtr_id_fk")  
    public List<VersaoTreinamento> getVersoesTreinamento() {  
        return versoesTreinamento;  
    }  

    //Entidade treinamento versão
    @ManyToOne
    @JoinColumn(name = "trn_id")
    private Treinamento treinamento;

Você até pode usar o relacionamento uni-direcional (somente o OneToMany), mas dai terias que referenciar a coluna no referencedColumnName (somente a partir do JPA 2.0).

//Entidade treinamento
    @OneToMany(name="trn_id", referencedColumnName="id", cascade =  CascadeType.ALL)  
    @ForeignKey(name = "sns_tre_vtr_id_fk")  
    public List<VersaoTreinamento> getVersoesTreinamento() {  
        return versoesTreinamento;  
    }
L

Testei desta maneira e funcionou, porem da um trabalhao pra salvar isso,

tenho que salvar o treinamento percorro a lista de versoesTreinamento e
pego versao a versao e seto o treinamento salvo, depois adiciono a lista de versoes
alterada ao treinamento e salvo ele novamente.
Isto é mto trabalho o hibernate nao deveria resolver isso pra mim???

E

Não precisa setar o objeto da versao_treinamento.

Só o

e depois salvar já cria o vínculo entre as tabelas do banco.

L

Tentei desta maneira e nao salva o id na tabela, tentei salvar o treinamento primeiro e depois incluir as versoes e salvar novamente o treinamento e tbm nao funcionou :frowning:

E

Posta o código das entidades treinamento e versaoTreinamento pra eu ver como ficou…

L
@SuppressWarnings("serial")
@Entity
@Table(name = "sns_treinamento")
@Inheritance(strategy = InheritanceType.JOINED)
@AttributeOverride(name = "id", column = @Column(name = "trn_id"))
public class Treinamento extends SnsAbstractEntity {

	private UsuarioSns usuarioSns;

	private List<VersaoTreinamento> versoesTreinamento;

	@OneToOne(cascade = CascadeType.ALL)
	@JoinColumn(name = "usu_id")
	@ForeignKey(name = "sns_trn_usu_id_fk")
	public UsuarioSns getUsuarioSns() {
		return usuarioSns;
	}

	public void setUsuarioSns(UsuarioSns usuarioSns) {
		this.usuarioSns = usuarioSns;
	}

	@OneToMany(cascade = CascadeType.ALL)
	@JoinColumn(name = "trn_id", referencedColumnName="trn_id")
	@ForeignKey(name = "sns_tre_vtr_id_fk")
	public List<VersaoTreinamento> getVersoesTreinamento() { 
		return versoesTreinamento;
	}

	public void setVersoesTreinamento(List<VersaoTreinamento> versoesTreinamento) {
		this.versoesTreinamento = versoesTreinamento;
	}

e Versao treinamento

@SuppressWarnings("serial")
@Entity
@Table(name = "sns_versao_treinamento")
@Inheritance(strategy = InheritanceType.JOINED)
@AttributeOverride(name = "id", column = @Column(name = "vtr_id"))
public class VersaoTreinamento extends SnsAbstractEntity {
	
	private VersaoDocumento versaoDocumento;
	
	private Boolean isTreinado;
	
	private Treinamento treinamento;
	
	
	

	

	@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@JoinColumn(name = "trn_id")
	@ForeignKey(name = "sns_trn1_ver_id_fk")
	public Treinamento getTreinamento() {
		return treinamento;
	}

	public void setTreinamento(Treinamento treinamento) {
		this.treinamento = treinamento;
	}

	@OneToOne(cascade = CascadeType.ALL)
	@JoinColumn(name = "ver_id")
	@ForeignKey(name = "sns_vtr_ver_id_fk")
	public VersaoDocumento getVersaoDocumento() {
		return versaoDocumento;
	}

	public void setVersaoDocumento(VersaoDocumento versaoDocumento) {
		this.versaoDocumento = versaoDocumento;
	}

	@Column(name = "vtr_isTreinado")
	public Boolean getIsTreinado() {
		return isTreinado;
	}

	public void setIsTreinado(Boolean isTreinado) {
		this.isTreinado = isTreinado;
	}
E

Cara, tu ta usando o relacionamento bi-direcional. Nesse caso não precisa usar joinColumn nos dois lados. Deixa só na versao_treinamento e usa o mappedBy em treinamento.

@OneToMany(mappedBy = "treinamento", cascade = CascadeType.ALL) @ForeignKey(name = "sns_tre_vtr_id_fk") public List<VersaoTreinamento> getVersoesTreinamento() { return versoesTreinamento; }

Outra dúvida, tem algum motivo pra vc mapear os getters e não os atributos?

L

Fiz esta alteracao mas nao funcionou, nao salva os ids na tabela, as anotacoes sao padrao dos sistemas aki, sempre utilizam anotacoes nos get’s, pq nao sei.

Criado 28 de dezembro de 2012
Ultima resposta 28 de dez. de 2012
Respostas 11
Participantes 3