javax.persistence.EntityManager: merge só pega e lança exceções se executar flush logo em seguida

04/03/2010

1

Usando Hibernate, SE, GlassFish e MySql   No código que está abaixo, tenho a situação em que está configurada a “violação de uma chave única” e ao executar o “merge” não são pegas e nem lançadas quaisquer exceções.   A única solução encontrada foi executar o “flush” logo após o “merge”, porém, não acho que faz sentido ter que executar outro comando para algo que deveria funcionar direto.   Existe outra forma de pegar e lançar este tipo de exceção?       /*  * Main.java  */   package enterpriseapplication;   import ejb.TabelaRemote; import entity.Tabela; import javax.ejb.EJB;   public class Main {       @EJB public static TabelaRemote t;       public Main() {         try {               // Esta linha provoca a violação de uma chave única,             // pois, o nome "José" já consta em outra linha da tabela.                         t.alterar(new Tabela(2, "José"));           } catch (Exception e) {                         // Aqui deveria imprimir a causa da exceção da violação da chave única, mas,             // é impresso "null".                         System.out.println(e.getCause());                     }     }       public static void main(String[] args) {         new Main();     }   }       - Estrutura da tabela do banco de dados:   CREATE TABLE  `teste`.`tabela` (   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,   `nome` varchar(50) NOT NULL,   PRIMARY KEY (`id`),   UNIQUE KEY `tabela_uk1` (`nome`) ) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=latin1;       - Dados inseridos na tabela do banco de dados:   insert tabela (nome) value ('José'); insert tabela (nome) value ('Maria');       - Código da Interface.   /*  * TabelaRemote.java  */   package ejb;   import entity.Tabela; import javax.ejb.Remote;   @Remote public interface TabelaRemote {     public void alterar(Tabela tabela) throws Exception; }     - Código do Session Bean.   /*  * TabelaBean.java  */   package ejb;   import entity.Tabela; import exception.EnterpriseApplicationException; import javax.ejb.Stateless; import javax.persistence.EntityExistsException; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext;   @Stateless public class TabelaBean implements TabelaRemote {       @PersistenceContext(unitName = "EnterpriseApplication-ejbPU")     private EntityManager em;       public void alterar(Tabela tabela) throws Exception {         try {             em.merge(tabela);                     // Aqui deveria pegar e lançar a exceção da violação da chave única,         // mas, nenhuma das exceções abaixo é considerada.                 } catch(EntityExistsException e) {             throw new EnterpriseApplicationException("EntityExistsException");                 } catch(Exception e) {             throw new Exception("Exception", e);         }       }   }       - Pojo da entidade:   /*  * Tabela.java  */   package entity;   import java.io.Serializable; import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table;   @Entity @Table(name = "tabela")   public class Tabela implements Serializable {     private static final long serialVersionUID = 1L;     @Id     @GeneratedValue(strategy = GenerationType.IDENTITY)     @Basic(optional = false)     @Column(name = "id")     private Integer id;     @Basic(optional = false)     @Column(name = "nome")     private String nome;       public Tabela() {     }       public Tabela(Integer id) {         this.id = id;     }       public Tabela(Integer id, String nome) {         this.id = id;         this.nome = nome;     }       public Integer getId() {         return id;     }       public void setId(Integer id) {         this.id = id;     }       public String getNome() {         return nome;     }       public void setNome(String nome) {         this.nome = nome;     }       @Override     public int hashCode() {         int hash = 0;         hash += (id != null ? id.hashCode() : 0);         return hash;     }       @Override     public boolean equals(Object object) {         if (!(object instanceof Tabela)) {             return false;         }         Tabela other = (Tabela) object;         if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {             return false;         }         return true;     }       @Override     public String toString() {         return "entity.Tabela[id=" + id + "]";     }   }       - persistence.xml   <?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">     <persistence-unit name="EnterpriseApplication-ejbPU" transaction-type="JTA">     <provider>org.hibernate.ejb.HibernatePersistence</provider>     <jta-data-source>Teste</jta-data-source>     <exclude-unlisted-classes>false</exclude-unlisted-classes>     <properties/>   </persistence-unit>   </persistence>       - sun-resources.xml   <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE resources PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Resource Definitions //EN" "http://www.sun.com/software/appserver/dtds/sun-resources_1_3.dtd">   <resources>     <jdbc-resource enabled="true" jndi-name="Teste" object-type="user" pool-name="mysql_Teste_rootPool"/>     <jdbc-connection-pool allow-non-component-callers="false" associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" connection-validation-method="auto-commit" datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" fail-all-connections="false" idle-timeout-in-seconds="300" is-connection-validation-required="false" is-isolation-level-guaranteed="true" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="false" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="mysql_Teste_rootPool" non-transactional-connections="false" pool-resize-quantity="2" res-type="javax.sql.DataSource" statement-timeout-in-seconds="-1" steady-pool-size="8" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">     <property name="User" value="root"/>     <property name="Password" value="root"/>     <property name="serverName" value="localhost"/>     <property name="portNumber" value="3306"/>     <property name="databaseName" value="Teste"/>     <property name="URL" value="jdbc:mysql://localhost:3306/Teste"/>     <property name="driverClass" value="com.mysql.jdbc.Driver"/>   </jdbc-connection-pool>  
Responder

Posts

05/03/2010

Dyego Carmo

Troque GenerationType.IDENTITY por GenerationType.AUTO

Responder

05/03/2010

Regina

Essa alteração Diego que me pediu não sofreu mudanças continua igual... não poderia ser o mysql com o provedor hibernate com glassfish que não estão se entendento??? já perquisei em varios lugares mais nada de achar a resposta... nem em outros foruns me respondão você foi o primeiro.
Responder
Ao que parece, o problema é uma discrepância entre o
que foi definido no BD e o que está mapeado na sua
entidade.

Experimente acrescentar
unique=true
na sua anotação @Column do atributo nome. Aí sim já
deve ocorrer exceção quando tentar dar o merge (desde
que a outra entidade com o mesmo nome já esteja
"gerenciada" pelo container).

Como não há restrição no EntityManager, ele aceita
o merge da entidade. Mas quando as alterações são
"descarregadas" para o BD, a restrição de integridade
do BD é que vai gerar a exceção.
Responder

05/03/2010

Regina

gostei da sua idéia tinha já me esquecido desse parâmetro no @column , mais não teve sucesso ... e estava gerenciada bonitinho mais... obrigado pela atenção caso tenha mais uma ai ???? agora estou pensando em atualizar meu netbeans, mysql, glassfish.
Responder