Galera, tenho uma pergunta simples para uma situação muito louca.
No meu sistema tem o seguinte código:
public boolean descricaoCadastrada(T adesao) {
Criteria criteria = sessao.createCriteria(this.classePersistente);
criteria.add(Restrictions.eq("descricao", adesao.getDescricao()));
criteria.add(Restrictions.ne("id",adesao.getId()));
return (criteria.uniqueResult() != null);
}
debugando o código quando o comando criteria.uniqueResult() vai ser executado, o comando SQL que aparece no console é: Hibernate: update Adesao set ativo=?, descricao=?, detalhamento=?, duracao=?, gratis=? where id=?
Bem, uma exceção é gerada porque o campo descrição é obrigatório…
O fato é que eu estou tentando alterar um objeto e esse método testa se existe alguma adesão cadastrada com a descrição cadastrada…
Já tentei de tudo e não consigo entender.
Segue abaixo a exceção gerada:
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:249)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:41)
at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:969)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1562)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:283)
at org.hibernate.impl.CriteriaImpl.uniqueResult(CriteriaImpl.java:305)
at apisaas.adesao.AdesaoDAOHibernate.descricaoCadastrada(AdesaoDAOHibernate.java:28)
at apisaas.adesao.AdesaoBusinessStrategy.validarDescricaoCadastrada(AdesaoBusinessStrategy.java:66)
at apisaas.adesao.AdesaoBusinessStrategy.validarAoSalvar(AdesaoBusinessStrategy.java:51)
at apisaas.adesao.AdesaoBusiness.salvar(AdesaoBusiness.java:36)
at apisaas.adesao.AdesaoBusiness.main(AdesaoBusiness.java:89)
Caused by: java.sql.BatchUpdateException: Duplicate entry 'Adesao2' for key 'descricao'
at com.mysql.jdbc.ServerPreparedStatement.executeBatch(ServerPreparedStatement.java:657)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeBatch(NewProxyPreparedStatement.java:1723)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:242)
... 13 more
Verifique se no seu mapeamento tem algo diferente da realidade do banco. Por exemplo já aconteceu comigo no .NET onde um campo no banco aceitava NULL mas o atributo não era nullable, então um valor null gravado no banco no hibernate vinha como zero para o objeto. Não sei se isso existe no Java, mas só quero exemplificar que se por algum motivo qualquer o hibernate hidratar os objetos de forma diferente do que está no banco, vai identificar que houve alteração e consequentemente vai querer fazer update. Se não for isso, pode ser algo no seu código que não tenha mostrado.
verifique se voce nao tem dois atributos mapeados para a mesma coluna…
Segue abaixo a minha classe:
package apisaas.adesao;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;
import apisaas.modulo.Modulo;
@Entity
@Table
@Inheritance(strategy=InheritanceType.JOINED)
public class Adesao implements Serializable {
private static final long serialVersionUID = 858345758170078424L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column
private int id;
@Column(length=50, nullable=false, unique=true)
@NotEmpty(message="Informe a descrição da adesão")
@Size(min=1, max=50, message="A descrição da adesão deve possuir no mínimo {min} e no máximo {max} caracteres")
private String descricao;
@Column(nullable=false)
@org.hibernate.annotations.Check(constraints="duracao > 0")
@Min(value=1, message="A duração da adesão deve ter no mínimo um mês")
private int duracao;
@Column(nullable=false)
@NotNull(message="Informe se a adesão é grátis ou não")
private boolean gratis;
@Lob
@Column(nullable=false)
@NotEmpty(message="Informe o detalhamento da adesão")
private String detalhamento;
@Column(nullable=false)
@NotNull(message="Informe se a adesão está ativa ou não")
private boolean ativo;
@ManyToMany(fetch=FetchType.EAGER)
@org.hibernate.annotations.Fetch(org.hibernate.annotations.FetchMode.SELECT)
@JoinTable(
name = "AdesaoModulo",
joinColumns = @JoinColumn(name = "adesao"),
inverseJoinColumns = @JoinColumn(name = "modulo"),
uniqueConstraints = @UniqueConstraint(columnNames = {"adesao", "modulo" })
)
@NotNull(message="Uma adesão deve estar associada a pelo menos um módulo")
private List<Modulo> modulos;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getDuracao() {
return duracao;
}
public void setDuracao(int duracao) {
this.duracao = duracao;
}
public String getDescricao() {
return descricao;
}
public void setDescricao(String descricao) {
this.descricao = descricao;
}
public boolean isGratis() {
return gratis;
}
public void setGratis(boolean gratis) {
this.gratis = gratis;
}
public String getDetalhamento() {
return detalhamento;
}
public void setDetalhamento(String detalhamento) {
this.detalhamento = detalhamento;
}
public boolean isAtivo() {
return ativo;
}
public void setAtivo(boolean ativo) {
this.ativo = ativo;
}
public List<Modulo> getModulos() {
return modulos;
}
public void setModulos(List<Modulo> modulos) {
this.modulos = modulos;
}
@Override
public boolean equals(Object arg0) {
if (this == arg0) {
return true;
}
if (!(arg0 instanceof Adesao))
{
return false;
}
Adesao planoInformado =(Adesao) arg0;
boolean mesmoId = (planoInformado.getId() == this.id);
boolean mesmaDescricao = planoInformado.getDescricao().equalsIgnoreCase(this.descricao);
return mesmoId && mesmaDescricao;
}
@Override
public int hashCode() {
return this.id == 0 ? System.identityHashCode(this) : this.id;
}
}
A questão é que quando eu vou fazer uma consulta pra verificar se existe uma adesão cadastrada com a descrição, dá erro de duplicação, mas a consulta e justamente pra ver se existe…
po, nao consegui ver o que pode estar acontecendo…
Galera é o seguinte…
O hibernate por padrão vem com o flushMode como AUTO, assim, a cada alteração de um objeto persistente, o comando é disparado para economizar na hora de executar o commit.
Eu tive que mudar para MANUAL e após os comandos de persistência, executar o flush e o clear.