Hibernate não cria tabela no MySQL e não persiste o produto - (Curso Spring MVC Alura)

Estou fazendo o curso de Spring MVC da Alura, estou na parte onde é realizado o cadastro de um produto, acontece que no front o ciclo é realizado normalmente, preenchimento do formulário de cadastro e envio das informações para persistência e retorno da mensagem de sucesso, porém no back o Hibernate não cria a entidade de produto no MySQL e não persiste o produto recuperado do formulário, e no log ele não exibe nenhuma mensagem de erro, exibe somente o out do objeto de produto e faz o retorno da página de produto cadastrado com sucesso que estão dentro do método gravar do controller de produto.

Estou desenvolvendo conforme o curso pede, o server utilizado é o tomcat.

Segue abaixo as classes do projeto e páginas JSP:

Formulário de cadastro de produto.

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Casa do Código</title>
    </head>
    <body>
        
        <form action="/casadocodigo/produtos" method="POST">
            <div>
                <label>Título</label>
                <input type="text" name="titulo"/>
            </div>
            <div>
                <label>Descrição</label>
                <textarea rows="10" cols="20" name="descricao"></textarea>
            </div>
            <div>
                <label>Páginas</label>
                <input type="text" name="paginas"/>
            </div>
            <button type="submit">Cadastrar</button>
        </form>
        
    </body>
</html>

Formulário de Sucesso que é exibo ao cadastrar o produto

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Casa do Código</title>
    </head>
    <body>
        <h1>Produto Cadastrado com sucesso!</h1>
    </body>
</html>

Classe de produto

@Entity
public class Produto {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    
    private String titulo;
    private String descricao;
    private int paginas;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
    
    public String getTitulo() {
        return titulo;
    }

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

    public String getDescricao() {
        return descricao;
    }

    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }

    public int getPaginas() {
        return paginas;
    }

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

    @Override
    public String toString() {
        return "Produto{" + "titulo=" + titulo + ", descricao=" + descricao + ", paginas=" + paginas + '}';
    }        
    
}

Controller de produto

@Controller
public class ProdutoController {
    
    @Autowired
    private ProdutoDAO produtoDAO;
    
    @RequestMapping("/produtos/form")
    public String form() {
        return "produtos/form";
    }
    
    @RequestMapping("/produtos")
    public String gravar(Produto produto) {
        System.out.println(produto);
        produtoDAO.gravar(produto);
        return "produtos/ok";
    }
    
}

DAO de produto

@Repository
@Transactional
public class ProdutoDAO {
    
    @PersistenceContext
    private EntityManager manager;
    
    public void gravar(Produto produto) {
        manager.persist(produto);
    }
    
}

Classes de configuração

@EnableTransactionManagement
public class JPAConfiguration {
    
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerfactory() {
        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        
        factoryBean.setJpaVendorAdapter(vendorAdapter);
        
        /***         
         * Configuração de conexão com o Banco de Dados
         */
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUsername("root");
        dataSource.setPassword("masterkey");
        dataSource.setUrl("jdbc:mysql://localhost:3306/casadocodigo");
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        
        factoryBean.setDataSource(dataSource);
        
        /***
         * Configuração do Hibernate
         */
        Properties props = new Properties();
        props.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
        props.setProperty("hibernate.show_sql", "true");
        props.setProperty("hibernate.hbm2ddl.auto", "update");
        
        factoryBean.setJpaProperties(props);
        
        factoryBean.setPackagesToScan("br.com.casadocodigo.loja.models");
        
        return factoryBean;
    }
    
    @Bean
    public JpaTransactionManager transactionManager(EntityManagerFactory emf) {
        return new JpaTransactionManager(emf);
    }
    
}

public class ServletSpringMVC extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] {AppWebConfiguration.class,JPAConfiguration.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }
    
}

@EnableWebMvc
@ComponentScan(basePackageClasses = {HomeController.class,ProdutoDAO.class})
public class AppWebConfiguration {
    
    @Bean
    public InternalResourceViewResolver InternalResourceViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    } 
    
}

O Hibernate chegou a gerar o SQL? O flush está sendo chamado?

E lembrando se está pagando o curso tente também tirar dúvida direto com o instrutor.

Acredito que não, pois de acordo com as configurações da classe JPAConfiguration ele deveria imprimir os SQL’s gerados no log, e isso não acontece!

Eu também fiz a pergunta diretamente para o instrutor do curso, porém como a demanda de atendimento é alta, eles demoram um certo tempo até responder, por este motivo resolvi perguntar aqui no GUJ também, de repente alguém aqui já havia passado pela mesma situação ou algo parecido e pudesse contribuir com essa dúvida, o que me daria um certo ganho de tempo na resolução em relação a resposta do instrutor.

Pelo menos com Hibernate puro lembro que tinha que chamar o flush, para o Hibernate gerar o SQL e enviar pro banco. Veja se falta algo relacionado a isso.

Sim realmente, concordo plenamente!
Vou tentar analisar mais profundamente minhas classes.
O maior problema é que o Spring faz todo esse controle sozinho, ele só precisa das configurações que constam na classe JPAConfiguration, o que faz com que os erros não sejam tão explícitos visivelmente falando.
Mas obrigado por sua ajuda @javaflex :slight_smile:

O JPA deve chamar o flush do hibernate no commit, entao veja se faltou chamar o commit.