Problema com Mapeamento JPA e Hibernate @Cascade

Bom dia, estou com um problema no mapeamento da minha entidade.

eu quero que quando a entidade não tiver id, ela persistir e quando tiver nao persisti.

Classe IdentifNota

@OneToMany(mappedBy = "parteEnvolvidaPK.numrIdentifNota", fetch=FetchType.EAGER)
@Fetch(FetchMode.SELECT)
@Cascade(CascadeType.ALL)
private Set<ParteEnvolvida> listParteEnvolvida;

Classe ParteEnvolvida

@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn (name = "ID_ENDERECO", nullable = true)
private Endereco endereco;

Dessa maneira ocorre uma exceção na hora de persistir a classe IdentifNota

Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: gov.sefaz.nfa.entidade.ParteEnvolvida.endereco -> gov.sefaz.nfa.entidade.gen.Endereco

Você pode ter cinco tipos de cascade válidos.

NONE=Não faz nada com o objeto, portanto é default e não é declarável na enum;

MERGE= Faz update nos filhos quando faz update no pai, aí está seu problema, se vc ainda não persistiu esse objeto não pode dar um update nele.

PERSIST = Salva o filho quando salva o pai, sendo assim, você pode dar um save ou persist no objeto, mas quando for dar update vai dar erro.

REFRESH = Salva o pai e mantem o filho sem alterar.

REMOVE = Remove o filho qdo remove o pai ou vice-versa;

ALL = Esse é o cascade do fim do mundo, você vai salva, fazer update, remover, o q quiser com seu objeto, é altamente não recomendável utilizá-lo.

Cuidado com essas propriedades se fizer mapeamento com mapped by, sempre coloque, se for extremamente necessário, o @Cascade no objeto pai.

Para o seu caso você pode combinar vários cascades para cada tipo de situação.



@Cascade(cascade={CascadeType.PERSIST,CascadeType.MERGE})  //salva em cascata, altera pai e filho em cascata


@Cascade(cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE})  //salva em cascata, altera pai e filho em cascata, exclui em cascata


@Cascade(cascade={CascadeType.PERSIST,CascadeType.REFRESH})  //salva em cascata, altera apenas o pai e mantem o filho (uso esse com alguma frequencia)

Oi ismael.costa.
Desde já agradeço a sua resposta. Foi bastante clara e me ajudou legal aqui. Mesmo assim eu queria aproveitar o ensejo para tirar mais uma dúvida. Você disse que o CascadeType.All deve ser evitado. So que eu uso ele direto aqui (talvez seja por isso que eu estou tendo alguns problemas sem noção >.> ). Faço isso porque quando, por exemplo, eu utilizo a entidade pai e em algum momento eu altero somente os filhos dele eu quero que esses filhos sejam atualizados. Mas se eu entendi o que você disse eu não preciso necessáriamente utilizado CascadeType.All para fazer isso, certo ?

Vou dar um exemplo que tenho aqui que acho que vai ficar melhor.
Eu tenho a entidade Aluno (student) que possui vários Cursos (StudentCourses). E tenho uma tela no qual o usuário pode ver os dados do aluno e seus cursos. Ou seja, para popular essa tela eu pego o Aluno pelo id e depois seus cursos com um get da collection que mapeia os filhos e tals. O usuário pode alterar somente os dados do Curso (filhos) e salvar. Então quando ele clica em “salvar” eu dou um update no Aluno com a intenção de salvar a alteração do Curso (mesmo que a entidade Aluno não tenha sido alterada). Então para que isso aconteça eu sempre imaginei que tivesse que por CascadeType.All no mapeamento dos filhos (Curso) na entidade do pai (Aluno).

Abaixo está um trexo do mapeamento:

@Entity
public class Student implements IFindRegistry {
	
	@Id @GeneratedValue
	private int			id;
	private String		name;
	/*
        ...
       */
	@OneToMany(mappedBy="student", cascade=CascadeType.ALL, orphanRemoval=true)
	@NotFound(action=NotFoundAction.IGNORE)
	private List<StudentCourse> studentCourses = new ArrayList<StudentCourse>();

       /*
        ...
       */
}

@Entity
public class StudentCourse {
	
	@Id @GeneratedValue
	private int id;
	private Date dateBegin;
	private Date dateEnd;
       /*
        ...
       */
	
	@OneToOne @JoinColumn(name="student")
	private Student student = new Student();
}

Desde já eu agradeço a ajuda!

Exatamente como vc entendeu, não é necessário o all, se vc quer ter todo o controle sobre ele basta colocar o
CascadeType.MERGE para qdo o aluno for salvo, salvar tbm o curso.

O ideal mesmo é vc ter um DAO pro filhos, pode até usar o CascadeType.PERSIST pra fazer o pai gravar, o CascadeType.REFRESH pra qdo for alterar
o aluno, e o CascadeType.REMOVE pra se precisar excluir um curso do aluno.

Mas eu faria um DAO pra tratar o update do filho, nem sempre vai funcionar como vc está esperando
, vai q vc muda algum valor da entidadade aluno sem querer e salva.

Abraços

Haaa! Beleza, entendi! Valeu mesmo pela ajuda Ismael!

Abraço!