1

I have been working on an application that uses Spring boot + MySQL Community Server as database.

My issue is if i use compound names like offeredServices i get this error on my browser:

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Fri Aug 04 21:15:23 EEST 2017
There was an unexpected error (type=Internal Server Error, status=500).
could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet

data.sql

INSERT INTO test(name, offeredServices) VALUES
  ('Test 1','Test 1'),
  ('Test 2','Test 2');

DROP DATABASE IF EXISTS v;
CREATE DATABASE v;
USE v;
CREATE TABLE test (
  id INT PRIMARY KEY auto_increment,
  name VARCHAR(40),
  serviceDescription VARCHAR(40)
);

But if i use short/simple name like nnnn it works

DROP DATABASE IF EXISTS v;
CREATE DATABASE v;
USE v;
CREATE TABLE test (
  id INT PRIMARY KEY auto_increment,
  name VARCHAR(40),
  nnnn VARCHAR(40)
);

INSERT INTO test(name, nnnn) VALUES
  ('Test 1','Test 1'),
  ('Test 2','Test 2');

From my class in java:

@Entity
@Table(name = "test")
public class Test {

    private int id;
    private String nnnn;
 public String getNnnn() {
        return nnnn;
    }
    public void setNnnn(String nnnn) {
        this.nnnn = nnnn;}

@Entity
@Table(name = "test")
public class Test {

    private int id;
    private String offeredServices;
 public String getOfferedServices() {
        return offeredServices;
    }
    public void setOfferedServices(String offeredServices) {
        this.offeredServices = offeredServices;}

My application.properties.

spring.datasource.url=jdbc:mysql://localhost:3306/v?autoReconnect=true&useSSL=false
spring.datasource.username=junior
spring.datasource.password=mypassword
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
server.port=8089

From my pom:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

I am not much with:

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop

Because it ignore my initial values.

Using spring.jpa.hibernate.ddl-auto=update gives the following error.

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2017-08-05 10:26:32.951 ERROR 6528 --- [           main] o.s.boot.SpringApplication               : Application startup failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1081) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:856) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at com.example.EmployeeLocatorApplication.main(EmployeeLocatorApplication.java:10) [classes/:na]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:954) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:882) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:370) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:359) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    ... 16 common frames omitted
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Unable to execute schema management to JDBC target [create table project (id integer not null auto_increment, name varchar(255), team_id integer not null, primary key (id)) ENGINE=InnoDB]
    at org.hibernate.tool.schema.internal.TargetDatabaseImpl.accept(TargetDatabaseImpl.java:59) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applySqlString(SchemaMigratorImpl.java:431) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applySqlStrings(SchemaMigratorImpl.java:420) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.tool.schema.internal.SchemaMigratorImpl.createTable(SchemaMigratorImpl.java:236) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigrationToTargets(SchemaMigratorImpl.java:167) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigration(SchemaMigratorImpl.java:60) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:134) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:101) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:472) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    ... 22 common frames omitted
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'project' already exists
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_131]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_131]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_131]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_131]
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) ~[mysql-connector-java-5.1.41.jar:5.1.41]
    at com.mysql.jdbc.Util.getInstance(Util.java:408) ~[mysql-connector-java-5.1.41.jar:5.1.41]
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:943) ~[mysql-connector-java-5.1.41.jar:5.1.41]
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973) ~[mysql-connector-java-5.1.41.jar:5.1.41]
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909) ~[mysql-connector-java-5.1.41.jar:5.1.41]
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527) ~[mysql-connector-java-5.1.41.jar:5.1.41]
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680) ~[mysql-connector-java-5.1.41.jar:5.1.41]
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2497) ~[mysql-connector-java-5.1.41.jar:5.1.41]
    at com.mysql.jdbc.StatementImpl.executeUpdateInternal(StatementImpl.java:1540) ~[mysql-connector-java-5.1.41.jar:5.1.41]
    at com.mysql.jdbc.StatementImpl.executeLargeUpdate(StatementImpl.java:2595) ~[mysql-connector-java-5.1.41.jar:5.1.41]
    at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1468) ~[mysql-connector-java-5.1.41.jar:5.1.41]
    at org.hibernate.tool.schema.internal.TargetDatabaseImpl.accept(TargetDatabaseImpl.java:56) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    ... 32 common frames omitted

------------------------------------------------------------------------
BUILD FAILURE
------------------------------------------------------------------------
Total time: 9.998s
Finished at: Sat Aug 05 10:26:33 EEST 2017
Final Memory: 10M/155M
------------------------------------------------------------------------
Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.2.1:exec (default-cli) on project my-project: Command execution failed. Process exited with an error: 1 (Exit value: 1) -> [Help 1]

To see the full stack trace of the errors, re-run Maven with the -e switch.
Re-run Maven using the -X switch to enable full debug logging.

For more information about the errors and possible solutions, please read the following articles:
[Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197

1 Answers1

1
SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet

SQLGrammarException is an exception related to sql syntax errors, but it doesn't give to much information of the root cause.

I was trying to replicate the same error using the same attribute names and table names and I found this:

  1. The Test table creation script is not related to the Test Java entity definition. There is a mismatch because test table create has a field called serviceDescription VARCHAR(40) but in the Test java class there is a totally diferent attribute name called offeredServices.
  2. The create table script has a field called name VARCHAR(40) but in the Test Java entity definition there is no name attribute.

Now lets assume that we have both components related the Database Table and the Java Entity Class. like this

Create Test table

    DROP DATABASE IF EXISTS v;
    CREATE DATABASE v CHARACTER SET utf8 COLLATE utf8_bin;
    USE v;
    CREATE TABLE test (
      id INT PRIMARY KEY auto_increment,
      name VARCHAR(40),
      offeredServices VARCHAR(40)
    );

Test java class

@Entity
@Table(name = "test")
public class Test {

    @Id
    @GeneratedValue
    private int id;

    private String name;

    private String offeredServices;

    public String getOfferedServices() {
        return offeredServices;
    }

    public void setOfferedServices(String offeredServices) {
        this.offeredServices = offeredServices;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

data.sql

INSERT INTO test(name, offeredServices) VALUES
  ('Test 1','Test 1'),
  ('Test 2','Test 2');

Test repository

    public interface TestRepository extends JpaRepository<Test,Integer> {}

Spring Boot Class

@SpringBootApplication
public class MysqlerrordemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(MysqlerrordemoApplication.class, args);
    }

    @Bean
    public CommandLineRunner runner( TestRepository testRepository){
        return (args) -> {
            testRepository.findAll().forEach(System.out::println);
        };
    }
}

When I run the application I have got the following error:

 SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'test0_.service_description' in 'field list'

This exception means that hibernate is converting the offeredServices attribute name (from camelCase) to offered_services column name (to SNAKE_CASE) because hibernate is using SpringNamingStrategy to generate table and column names.

To solve the problem just add a @Column(name="offeredservices") annotation to the offeredServices attribute. The @Column(name="offeredservices") annotation tells to hibernate that dont try to convert the camelCase attribute name to SNAKE_CASE, just keep column name in lowercase.

This is the final version of Test java class.

@Entity
@Table(name = "test")
public class Test {

    @Id
    @GeneratedValue
    private int id;

    private String name;

    @Column(name="offeredservices")
    private String offeredServices;

    public String getOfferedServices() {
        return offeredServices;
    }

    public void setOfferedServices(String offeredServices) {
        this.offeredServices = offeredServices;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

To get a very clear answer about this go to the this post spring-boot-jpa-column-name-annotation-ignored

Please also keep the spring.jpa.hibernate.ddl-auto property to create-drop

spring.jpa.hibernate.ddl-auto=create-drop
Daniel C.
  • 5,418
  • 3
  • 23
  • 26