Jpa cascade all and join column

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.

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)

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.

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

lgGodoy,

Nos relacionamentos OneToMany, você deve usar o relacionamento bi-direcional, ou seja, mapear os relacionamentos nas duas entidades.

[code]
//Entidade treinamento
@OneToMany(mappedBy = “treinamento”, cascade = CascadeType.ALL)
@ForeignKey(name = “sns_tre_vtr_id_fk”)
public List getVersoesTreinamento() {
return versoesTreinamento;
}

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

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; }

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???

Não precisa setar o objeto da versao_treinamento.

Só o

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

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:

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


@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;
	}

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?

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.