4
respostas

org.hibernate.exception.SQLGrammarException: could not execute statement

Estou recebendo o seguinte erro quando vou rodar o teste:

javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute statement
Caused by: java.sql.SQLSyntaxErrorException: Table 'casadocodigo_test.produto' doesn't exist

Parece que o Hibernate não está criando as tabelas no banco de teste.

public class DataSourceConfigurationTest {

    @Bean
    @Profile("test")
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUsername("root");
        dataSource.setPassword("0000");
        dataSource.setUrl("jdbc:mysql://localhost:3306/casadocodigo_test");
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setConnectionProperties(getConnectionProperties());

        return dataSource;
    }

    private Properties getConnectionProperties() {
        Properties connectionProperties = new Properties();
        connectionProperties.setProperty("useTimezone", "true");
        connectionProperties.setProperty("serverTimezone", "UTC");
        connectionProperties.setProperty("useSSL", "false");

        return connectionProperties;
    }
}
@EnableTransactionManagement 
public class JPAConfiguration {

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
        factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        factoryBean.setDataSource(dataSource);
        factoryBean.setJpaProperties(aditionalProperties());
        factoryBean.setPackagesToScan("br.com.casadocodigo.loja.models");

        return factoryBean;
    }

    @Bean
    @Profile("dev")
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUsername("root");
        dataSource.setPassword("0000");
        dataSource.setUrl("jdbc:mysql://localhost:3306/casadocodigo");
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setConnectionProperties(getConnectionProperties());

        return dataSource;
    }

    @Bean
    public JpaTransactionManager transactionManager(EntityManagerFactory emf) {
        return new JpaTransactionManager(emf);
    }

    private Properties getConnectionProperties() {
        Properties connectionProperties = new Properties();
        connectionProperties.setProperty("useTimezone", "true");
        connectionProperties.setProperty("serverTimezone", "UTC");
        connectionProperties.setProperty("useSSL", "false");
        return connectionProperties;
    }

    private Properties aditionalProperties() {
        Properties props = new Properties();
        props.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
        props.setProperty("hibernate.show_sql", "true");
        props.setProperty("hibernate.hbm2ddl.auto", "update");
        return props;
    }
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { JPAConfiguration.class, ProdutoDao.class, DataSourceConfigurationTest.class })
@ActiveProfiles("test")
public class ProdutoDaoTest {

    @Autowired
    private ProdutoDao produtoDao;

    @Test
    @Transactional
    public void deveSomarTodosOsPrecosPorTipoLivro() {

        List<Produto> livrosImpressos = ProdutoBuilder.newProduto(TipoPreco.IMPRESSO, BigDecimal.TEN).more(3)
                .buildAll();

        List<Produto> livrosEbook = ProdutoBuilder.newProduto(TipoPreco.EBOOK, BigDecimal.TEN).more(3).buildAll();

        livrosImpressos.stream().forEach(produtoDao::grava);
        livrosEbook.stream().forEach(produtoDao::grava);

        BigDecimal valor = produtoDao.somaPrecosPorTipo(TipoPreco.EBOOK);
        Assert.assertEquals(new BigDecimal(40).setScale(2), valor);
    }
}

Alguém poderia me ajudar?

4 respostas

Olá Fábio, acredito que sua base de dados de testes não é criada e dá erro de sintaxe com SQLGrammarException pq você não setou o dialeto e outras propriedades do hibernate como fez na classe JPAConfiguration. Ex:

   props.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
    props.setProperty("hibernate.show_sql", "true");
    props.setProperty("hibernate.hbm2ddl.auto", "update");

Faça isso e teste novamente. Se o erro persistir, poste aqui novamente.

O método entityManagerFactory não é chamado em todos os casos? Achei que nos dois profiles ele passava por ali. Eu até resolvi alterando de:

props.setProperty("hibernate.hbm2ddl.auto", "update");

para

props.setProperty("hibernate.hbm2ddl.auto", "create");

e depois voltei para update de novo, mas como o professor não fez isso, eu queria descobrir o motivo de não funcionar.

Obrigado!

Olá Fábio, desculpe, você tem razão. Revendo a parte do curso é isso mesmo. Apenas diferenciamos com o profile os dados do banco, ou seja, do datasource. Modificando de update para create resolveu?

Você chegou a acrescentar o método onStartup() na ServletSpringMVC?

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
    super.onStartup(servletContext);
    servletContext.addListener(new RequestContextListener());
    servletContext.setInitParameter("spring.profiles.active", "dev");
}

Resolveu sim, ai depois alterei pra update novamente. Não sei se pode ter relação com o mySql, estou usando a versão 8 se não me engano. Coloquei o método onStartup sim.