@ManyToOne sem Cascade fazendo update sem necessidade

9 respostas
febatata

Olá pessoal, tudo bem?
Bom, vamos direto ao ponto.
Temos aqui uma entidade mapeada (JPA HIBERNATE).

.
.
.
public class RespostaQuestao extends BaseEntityIntelligere implements Comparable<RespostaQuestao> {

	@Id
	@GeneratedValue(generator="respostaquestao_s", strategy = GenerationType.SEQUENCE)
	private Long id;
	
	@ManyToOne
	@JoinColumn(name="tentativa_id")
	private Tentativa tentativa;
	
	@ManyToOne
	@JoinColumn(name="revisaoquestao_id")
	private RevisaoQuestao revisaoQuestao;
.
.
.

Meu problema é o seguinte:
Quando eu crio um objeto do tipo RespostaQuestao e o persisto, o hibernate está fazendo um update automático na tabela RevisaoQuestao, que é mapeada por esse @ManyToOne com @JoinColumn aí acima.

Vocês sabem como fazer para que esse update não aconteça? Já que na verdade só estou criando um objeto que usa o ID da RevisaoQuestao como FK?
Isso está gerando problemas de concorrência aqui, pois temos controle de Lock Otimista com @Version.
Quando uma primeira pessoa faz esse update, tudo bem. Agora quando um segundo fulano vai efetuar o update, ele diz que o objeto já foi alterado por outra transaction, lançando exceção do Hibernate.

Alguém pode me ajudar?
Obrigado a todos!

[Alterei o título de “@OneToMany” para “@ManyToOne”]

9 Respostas

Rodrigo_Sasaki

Como você está persistindo esse cara? Quem controla as transações?

febatata

Cara, o projeto usa Spring, ele que controla as transações. No caso tenho um bean do Spring que chama um Dao Genérico, que usa o HibernateTemplate do Spring.

joede.fadel

Você necessita que seja realizado o insert inicialmente? Caso não tem a anotation @Transient

@Transient
 public getRevisaoQuestao()....
ddenis3526

Amigo , a solução é add isso no seu @JoinCoumn

Esperto ter ajudado :smiley:

Hebert_Coelho

Estou querendo simular seu erro aqui.

Me diz aí, o RespostaQuestao tem por herança BaseEntityIntelligere.

A classe BaseEntityIntelligere é uma entidade também? Sua herança ela é mapeada ou não?

febatata

Hebert Coelho:
Estou querendo simular seu erro aqui.

Me diz aí, o RespostaQuestao tem por herança BaseEntityIntelligere.

A classe BaseEntityIntelligere é uma entidade também? Sua herança ela é mapeada ou não?

Cara, o BaseEntity é bem simples, na verdade ele poderia até ser uma interface. Só tem métodos abstratos.

A única coisa que prende um pouco é esse método isNew, mas que também daria para fazer alguns ajustes.

Até aonde eu entendo, o problema não está aqui, mas segue o código da mesma:

public abstract class BaseEntityIntelligere implements BaseEntity {

	private static final long serialVersionUID = -8981232280959410370L;

	public boolean isNew() {
		return getId() == null;
	}

	@Override
	public abstract boolean equals(final Object obj);

	@Override
	public abstract int hashCode();

	@Override
	public abstract String toString();
	
	public abstract BaseEntityIntelligere validar();
}
Hebert_Coelho
febatata:
Cara, o BaseEntity é bem simples, na verdade ele poderia até ser uma interface. Só tem métodos abstratos.

A única coisa que prende um pouco é esse método isNew, mas que também daria para fazer alguns ajustes.

Até aonde eu entendo, o problema não está aqui, mas segue o código da mesma:
public abstract class BaseEntityIntelligere implements BaseEntity {

	private static final long serialVersionUID = -8981232280959410370L;

	public boolean isNew() {
		return getId() == null;
	}

	@Override
	public abstract boolean equals(final Object obj);

	@Override
	public abstract int hashCode();

	@Override
	public abstract String toString();
	
	public abstract BaseEntityIntelligere validar();
}
Eu também acho que não. É por que vou simular aqui. Fazer um insert e ver se rola um update. Quero ver como se comporta. Vou fazer uma coisa simples, um JSE com duas classes Main, uma para criar o objeto revisaoQuestao e outra para fazer o insert RespostaQuestao e ver se o mesmo acontece.

Eu to suspeitando que pode ser a implementação que você está utilizando, como o objeto pode estar detached, ele pode estar fazendo um merge automático para você não ter esse problema. Pelo menos eu já vi isso acontecer com o EclipseLink.

Bem, depois que eu pensei na teoria acima, como está o código do seu persist?

febatata
Hebert Coelho:
febatata:
Cara, o BaseEntity é bem simples, na verdade ele poderia até ser uma interface. Só tem métodos abstratos.

A única coisa que prende um pouco é esse método isNew, mas que também daria para fazer alguns ajustes.

Até aonde eu entendo, o problema não está aqui, mas segue o código da mesma:
public abstract class BaseEntityIntelligere implements BaseEntity {

	private static final long serialVersionUID = -8981232280959410370L;

	public boolean isNew() {
		return getId() == null;
	}

	@Override
	public abstract boolean equals(final Object obj);

	@Override
	public abstract int hashCode();

	@Override
	public abstract String toString();
	
	public abstract BaseEntityIntelligere validar();
}
Eu também acho que não. É por que vou simular aqui. Fazer um insert e ver se rola um update. Quero ver como se comporta. Vou fazer uma coisa simples, um JSE com duas classes Main, uma para criar o objeto revisaoQuestao e outra para fazer o insert RespostaQuestao e ver se o mesmo acontece.

Eu to suspeitando que pode ser a implementação que você está utilizando, como o objeto pode estar detached, ele pode estar fazendo um merge automático para você não ter esse problema. Pelo menos eu já vi isso acontecer com o EclipseLink.

Bem, depois que eu pensei na teoria acima, como está o código do seu persist?

Cara, os meus objetos estão todos gerenciados. Eu acabei de buscar o RevisaoQuestao e dei o set no RespostaQuestao para ele entender a FK.

Pensei que fosse ao contrário, se eu mandasse o RevisaoQuestao detached, ele iria funcionar. Mas eu testei e também não consegui.

O meu persist é simples também. Veja o salvar do meu BaseDao
protected T saveOrUpdate(final T entidade) {
		try {
			if (entidade.isNew()) {
				getHibernateTemplate().persist(entidade);
			} else {
				return getHibernateTemplate().merge(entidade);
			}
			return entidade;
		} catch (Exception ex) {
			throw new DaoException(ERRO_SALVAR, new Object[]{entidade.getClass().getName()}, ex);
		}
	}
Hebert_Coelho

Blz. Agora como que você está montando o objeto? Passando as referências?

Criado 30 de outubro de 2012
Ultima resposta 30 de out. de 2012
Respostas 9
Participantes 5