Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

Dúvida no Ex. 12 da Aula 2 - Cadastro de produtos

Estou tentando fazer o último exercício da aula2, que no final das contas devemos cadastrar os produtos da Casa do Código, porém depois de configurar tudo conforme os exercícios o navegador apresenta a seguinte mensagem de erro:

HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalArgumentException: Unknown entity: br.com.casadocodigo.loja.models.Produto

type Exception report

message Request processing failed; nested exception is java.lang.IllegalArgumentException: Unknown entity: br.com.casadocodigo.loja.models.Produto

description The server encountered an internal error that prevented it from fulfilling this request.

exception

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: Unknown entity: br.com.casadocodigo.loja.models.Produto
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:973)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

root cause

java.lang.IllegalArgumentException: Unknown entity: br.com.casadocodigo.loja.models.Produto
    org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1184)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:606)
    org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:289)
    com.sun.proxy.$Proxy22.persist(Unknown Source)
    br.com.casadocodigo.loja.daos.ProdutoDAO.gravar(ProdutoDAO.java:18)
    br.com.casadocodigo.loja.daos.ProdutoDAO$$FastClassBySpringCGLIB$$92ebe7c5.invoke(<generated>)
    org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
    org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:266)
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
    br.com.casadocodigo.loja.daos.ProdutoDAO$$EnhancerBySpringCGLIB$$619e6cdc.gravar(<generated>)
    br.com.casadocodigo.loja.controllers.ProdutosController.grava(ProdutosController.java:28)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:606)
    org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

note The full stack trace of the root cause is available in the Apache Tomcat/8.0.30 logs.
Apache Tomcat/8.0.30

No mysql criei a tabela Produto e também tentei com a tabela produto. Existe alguma regra para criar a tabela no banco de dados?

Obrigado

5 respostas

Oi Joacir,

Coloca o código da sua classe Produto aqui para dar uma olhada por favor, e também a classe de configuração, blz?

Sobre criar a tabela, lembra que não precisa criar na mão, pois o Hibernate vai criar as tabelas baseado nas nossas entidades. Se ele não criou a tabela, então deve ter algum problema na sua configuração.

Coloca os códigos aqui que analisamos.

Abraço

Durante esta aula 2 não foi dito que a tabela de produtos seria criada automaticamente. Outra coisa: durante os vídeos não foi falado como criar o banco de dados. Seria melhor se tivesse embutido no projeto um HSQL já que aula tem foco no Spring MVC.

Abaixo segue as classes. Um detalhe é que na classe produto a aula não pediu para usar a notação @Entity então a classe Produto não tem ela listada, porém testei com esta anotação mesmo assim e não tive sucesso.

package br.com.casadocodigo.loja.models;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

public class Produto {

    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    private String titulo;
    private String sinopse;
    private int paginas;

    public String getTitulo() {
        return titulo;
    }

    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }

    public String getSinopse() {
        return sinopse;
    }

    public void setSinopse(String sinopse) {
        this.sinopse = sinopse;
    }

    public int getPaginas() {
        return paginas;
    }

    public void setPaginas(int paginas) {
        this.paginas = paginas;
    }

}
package br.com.caelum.loja.conf;

import java.util.Properties;

import javax.persistence.EntityManagerFactory;

import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@EnableTransactionManagement
public class JPAConfiguration {
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        JpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();

        factoryBean.setJpaVendorAdapter(jpaVendorAdapter );

        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        System.out.println("========== 1");
        dataSource.setUsername("root");
        System.out.println("========== 2");
        dataSource.setPassword("root");
        System.out.println("========== 3");
        dataSource.setUrl("jdbc:mysql://localhost:3306/casadocodigo");
        System.out.println("========== 4");
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        System.out.println("========== 5");

        factoryBean.setDataSource(dataSource);
        System.out.println("========== 6");

        Properties props = new Properties();
        System.out.println("========== 7");
        props.setProperty("hibernate.dialect" , "org.hibernate.dialect.MySQL5Dialect");
        System.out.println("========== 8");
        props.setProperty("hibernate.show_sql", "true");
        System.out.println("========== 9");
        props.setProperty("hibernate.hbm2ddl.auto", "update");
        System.out.println("========== 10");

        factoryBean.setJpaProperties(props);
        System.out.println("========== 11");

        factoryBean.setPackagesToScan("br.com.caelum.loja.models");
        System.out.println("========== 12");

        return factoryBean;

    }

    @Bean
    public JpaTransactionManager transactionManager(EntityManagerFactory emf) {
        System.out.println("========== 13");
        return new JpaTransactionManager(emf);
    }

}

Obrigado

Debuguei o código e tenho mais algumas informações. A classe que dispara o erro é a classe abstrata AbstractEntityManagerImpl do pacote org.hibernate.jpa.spi e o erro acontece no método persist disparando a exception MappingException. Segue abaixo o método que dispara a exception:

public void persist(Object entity) {
        checkOpen();
        try {
            internalGetSession().persist( entity );
        }
        catch ( MappingException e ) {
            throw convert( new IllegalArgumentException( e.getMessage() ) ) ;
        }
        catch ( RuntimeException e ) {
            throw convert( e );
        }
    }
solução!

Oi Joacir,

O HSQLDB poderia ser usado. Mas como ele é um banco muito distante dos ambientes de produção, preferimos usar um banco que estivesse mais próximo do dia a dia dos desenvolvedores. O mysql continua não sendo o foco, por isso deixamos o Hibernate cuidar do banco de dados.

Talvez tenha passado despercebido, mas na aula 2 (https://cursos.alura.com.br/course/spring-mvc-1-criando-aplicacoes-web/section/2/2) no minuto 21:20 eu falo que o Hibernate cuidará do banco de dados, assim, não precisamos nos preocupar com isso. Por isso você não precisa criar as tabelas na mão.

Outro detalhe é que você precisa da annotation @Entity. Também no mesmo vídeo acima, no minuto 1:54 você verá que explico e coloco o @Entity.

Coloque o @Entity.

Vi um erro na sua configuração. Você está usando o pacote br.com.casadocodigo.loja.models na classe Produto, porém na configuração, você colocou:

factoryBean.setPackagesToScan("br.com.caelum.loja.models");

Mude para:

factoryBean.setPackagesToScan("br.com.casadocodigo.loja.models");

Isso deve fazer seu código funcionar.

Se tiver outros problemas, pode falar.

Abraço

De fato o erro estava no código factoryBean.setPackagesToScan("br.com.caelum.loja.models"); que deveria substituir por factoryBean.setPackagesToScan("br.com.casadocodigo.loja.models");.

Ainda assim senti falta de uma explicação mais apurada sobre a utilização do mysql ou um link para tal informação.

Obrigado novamente

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software