Object references an unsaved transient instance

22 respostas
D

Prezados,
estou tentando salvar os dados de um formulário no banco, só que ele me retorna essa mensagem “object references an unsaved transient instance - save the transient instance before flushing: … entity.CursoEspecializacao”

Dei umas olhadas nos post ai e diziam que tinha que colocar cascade = CascadeType.ALL, só que não adiantou.

Segue as entity e o save

Entity Pessoa

. . .
@OneToMany(mappedBy ="pessoa", fetch = FetchType.LAZY)
	private List<CursoEspecializacao> cursoEspecializacao;
. . .

Entity CursoEspecializacao

. . .
	@ManyToOne
	@JoinColumn(name="Pessoa_idPessoa")
	private Pessoa pessoa = new Pessoa();
. . .

save

public void salvarPessoa(Pessoa pessoa) {
		try {
			entityManager.merge(pessoa);
			entityManager.flush();
		} catch (Exception e) {
		//TODO ...
		}
	}

Se alguem puder ajudar eu agradeço.

22 Respostas

drsmachado

Como está a classe CursoEspecializacao? Pode posta-la por completo?

D

Segue a entity cursoEspecializacao

@Table(name = "CursoEspecializacao", schema = "SPL")
public class CursoEspecializacao implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "idCursoEspecializacao", unique = true, nullable = false)
	private Integer idCursoEspecializacao;
	
	@Column(name = "especializacao")
	private String especializacao;
	
	@Column(name = "nomeInstituicao")
	private String nomeInstituicao;
	
	@ManyToOne
	@JoinColumn(name="Pessoa_idPessoa")
	private Pessoa pessoa = new Pessoa();
//GETTERES AND SETTERES 
. . .
D

Segue a entity cursoEspecialização. Só não consta os getteres e setteres

@Table(name = "CursoEspecializacao", schema = "SPL")
public class CursoEspecializacao implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "idCursoEspecializacao", unique = true, nullable = false)
	private Integer idCursoEspecializacao;
	
	@Column(name = "especializacao")
	private String especializacao;
	
	
	@Column(name = "nomeInstituicao")
	private String nomeInstituicao;
	
	@ManyToOne
	@JoinColumn(name="Pessoa_idPessoa")
	private Pessoa pessoa = new Pessoa();
nel

Cara, é EJB ou “na mão” mesmo ?
Tu não está presente em nenhum transação, por isso ele não consegue persistir, como se não houvesse um contexto.

Rodrigo_Sasaki

eu acho que sua entidade CursoEspecializacao está detached na hora de persistir, portanto pode ser necessário buscar a referência dela novamente.
algo assim:public void salvarPessoa(Pessoa pessoa) { try { pessoa.setCursoEspecializacao(entityManager.getReference( CursoEspecializacao.class, pessoa.getCursoEspecializacao().getIdCursoEspecializacao())); entityManager.merge(pessoa); entityManager.flush(); } catch (Exception e) { //TODO ... } }

D

digaoneves, não entendi muito bem o que você, mas o meu método de salvar está assim:

action

public void salvarPessoa(){
this.pessoa.setCursoEspecializacao(listaCursoEspecializacao);
this.cadastroManager.salvarPessoa(pessoa)
}

save

public void salvarPessoa(Pessoa pessoa) {  
            try {  
                entityManager.merge(pessoa);  
                entityManager.flush();  
            } catch (Exception e) {  
            //TODO ...  
            }  
        }
D

nel:
Cara, é EJB ou “na mão” mesmo ?
Tu não está presente em nenhum transação, por isso ele não consegue persistir, como se não houvesse um contexto.

EJB mesmo

Rodrigo_Sasaki

Adapte o código que eu passei de modo que possa tratar uma lista.

EDIT: Aliás, você tentou usar o persist ao invés do merge ?

nel

david.jv:
nel:
Cara, é EJB ou “na mão” mesmo ?
Tu não está presente em nenhum transação, por isso ele não consegue persistir, como se não houvesse um contexto.

EJB mesmo

digaoneves:
Adapte o código que eu passei de modo que possa tratar uma lista.

EDIT: Aliás, você tentou usar o persist ao invés do merge ?

Merge também funciona. Ele vai identificar que não tem uma chave primária e persiste.
Estou achando que ele está usando uma classe comum e tentando injetar um EntityManager nela…posta a classe por completo colega, a que executa a persistência.

D

digaoneves:
Adapte o código que eu passei de modo que possa tratar uma lista.

EDIT: Aliás, você tentou usar o persist ao invés do merge ?

Tentei, só que ele me retorna o erro dizendo que o idPessoa não pode ser null.

D

Segue a class

@Name("cadastroManager")
@SuppressWarnings("unchecked")
public class CadastroManager extends AbstractManager {

	//. . . outros métodos


	public void salvarPessoa(Pessoa pessoa) {
		try {
			entityManager.merge(pessoa);
			entityManager.flush();
		} catch (Exception e) {
			//TODO ...
		}
	}
}
nel
david.jv:
Segue a class
@Name("cadastroManager")
@SuppressWarnings("unchecked")
public class CadastroManager extends AbstractManager {

	//. . . outros métodos


	public void salvarPessoa(Pessoa pessoa) {
		try {
			entityManager.merge(pessoa);
			entityManager.flush();
		} catch (Exception e) {
			//TODO ...
		}
	}
}

O que eu disse né...onde isso é um EJB ? Cadê as anotações ? Stateless? Statefull ? Singleton? Estou vendo nenhuma anotação EJB.
Isso dai nada mais é que um classe qualquer aos olhos de um servidor de aplicação colega...

Rodrigo_Sasaki

ah sim, como está configurada a PK da sua Pessoa ? e qual banco você usa ?

D

Na verdade isto vai ser adaptado para um EJB, esse teste está sendo feito na pq não consegui fazer essa ‘jossa’ funcionar.

nel

A PK dele é essa:

@Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "idCursoEspecializacao", unique = true, nullable = false) private Integer idCursoEspecializacao;

Eu faria duas mudanças ai:

1 - Tirar esse unique. Já tem o @Id, é óbvio que será unique.

2 - Trocaria o GenerationType.IDENTITY por GenerationType.AUTO. Já tive problemas com o modo IDENTITY, não é 100% confiável. E já testei com MySQL, Oracle, SQL Server…

Rodrigo_Sasaki

Essa PK é de CursoEspecializacao

nel

Mas faça o teste de forma coerente colega, senão isso não lhe trará os resultados esperados, e caso traga, pode ser apenas uma “enganação”. Se ele será um EJB, faça-o desde agora, é o correto.

nel

Perfeito. É a entidade Pessoa, desculpe. De qualquer forma, a minha observação sobre usar GenerationType.AUTO continua.
Grato pela observação.

Rodrigo_Sasaki

Mas faça o teste de forma coerente colega, senão isso não lhe trará os resultados esperados, e caso traga, pode ser apenas uma “enganação”. Se ele será um EJB, faça-o desde agora, é o correto.
++
Concordo plenamente. Na sua situação esse teste sem utilizar o EJB pode mais atrapalhar do que ajudar.

D

O banco de dados é mysql e a PK de pessoa segue abaixo:

@Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "idPessoa", unique = true, nullable = false) private Integer idPessoa;

Vou fazer o que você falou. Obrigado pelo toque.


Eu faria duas mudanças ai:

1 - Tirar esse unique. Já tem o @Id, é óbvio que será unique.

2 - Trocaria o GenerationType.IDENTITY por GenerationType.AUTO. Já tive problemas com o modo IDENTITY, não é 100% confiável. E já testei com MySQL, Oracle, SQL Server…

Vou fazer essas alterações. Mas pq o IDENTITY não é 100% ?

nel

Ao que me recordo brevemente, parece que ele tem problemas com banco que não possuem a implementação de auto incremento ou até mesmo não estejam configurado para o mesmo, por isso aconselho a devida alteração. Particularmente, já tive problemas com o mesmo.

D

Me desculpe pela demora em retornar ao fórum, tive problemas com minha internet.
Bem, primeiro agradeço ao nel por explicar o motivo. Fiz as alterações que vc falou.

digaoneves, tentei fazer a alteração que você falou, só que não deu certo.
Não dá pra mim fazer um getIdCursoEspecializacao(), pq é um list.
Tentei passar a class CursoEspecializacao por parâmetro, mas não deu certo.

<blockquote>

public void salvarPessoa(Pessoa pessoa) {

try {

pessoa.setCursoEspecializacao(entityManager.getReference(

CursoEspecializacao.class, pessoa.getCursoEspecializacao().getIdCursoEspecializacao()));  // O erro está aqui.

entityManager.merge(pessoa);

entityManager.flush();

} catch (Exception e) {

//TODO …

}

}</blockquote>

public void salvarPessoa(Pessoa pessoa, CursoEspecializacao cursoEspecializacao) { try { pessoa.setCursoEspecializacao(entityManager.getReference( CursoEspecializacao.class, cursoEspecializacao.getIdCursoEspecializacao())); // O erro está aqui. entityManager.merge(pessoa); entityManager.flush(); } catch (Exception e) { //TODO ... } }

Se vcs tirem alguma outra solução

Criado 27 de maio de 2012
Ultima resposta 2 de jun. de 2012
Respostas 22
Participantes 4