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

04/03/2010

3

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

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários. Para saber mais sobre o uso de cookies,
consulte nossa política de privacidade. Ao continuar navegando em nosso site, você concorda com a nossa política.

Aceitar