10

I am using H2 in-memory database for my springboot application. Where I have enabled hibernate.ddl-auto. I am getting below exception while hibernate is creating a schema

Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException:
Syntax error in SQL statement "CREATE TABLE PRODUCT_OFFSET_INFO (ID BIGINT NOT NULL, MODIFIED_TIMESTAMP TIMESTAMP, OFFSET[*] BIGINT, TOPIC_NAME VARCHAR(255), PRIMARY KEY (ID))"; expected "identifier"; SQL statement:
create table PRODUCT_OFFSET_INFO (ID bigint not null, MODIFIED_TIMESTAMP timestamp, OFFSET bigint, TOPIC_NAME varchar(255), primary key (ID)) [42001-200]
'''

Below is the Entity class:

@Entity
@Table(name="PRODUCT_OFFSET_INFO")
public class ProductOffsetInfo implements Serializable
{
   private static final long serialVersionUID = -2147468513335906679L;
    
   @Id
   @Column(name="ID")
   private Long ProductId;
    
   @Column(name="TOPIC_NAME")
   private String topic_name;
    
   @Column(name="OFFSET")
   private Long offset;
    
   @Column(name = "MODIFIED_TIMESTAMP")
   private Date modified;
    
   public Long getProductId() {
       return ProductId;
   }
   public void setProductId(Long ProductId) {
       this.ProductId = ProductId;
   }
    
   public String getTopic_name() {
       return topic_name;
   }
   public void setTopic_name(String topic_name) {
       this.topic_name = topic_name;
   }
    
   public Long getOffset() {
       return offset;
   }
   public void setOffset(Long offset) {
       this.offset = offset;
   }
    
   public Date getModified() {
       return modified;
   }
    
   public void setModified(Date modified) {
       this.modified = modified;
   }
}

Below is the database config file:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    entityManagerFactoryRef = "productEntityManagerFactory",
    transactionManagerRef = "productTransactionManager",
    basePackages = {"com.product.repository.product"}
)
@ComponentScan({"com.product.repository.product.impl"})
@EntityScan({"com.product.commons.entities.product.models","com.product.models.product"})
public class ProductDbConfig {

        @Autowired
        private JpaProperties jpaProperties;
        @Primary
        @Bean("productHikariConfig")
        @ConfigurationProperties(prefix = "spring.datasource")
        public HikariConfig hikariConfig() {
            return new HikariConfig();
        }
    
        @Primary
        @Bean(name = "productDataSource")
        @DependsOn("productHikariConfig")
        public DataSource dataSource(@Qualifier("productHikariConfig") HikariConfig hikariConfig) {
            return new HikariDataSource(hikariConfig);
        }
    
        @Primary
        @Bean(name = "productEntityManagerFactory")
        @PersistenceContext(unitName = "product")
        public LocalContainerEntityManagerFactoryBean entityManagerFactory(
                EntityManagerFactoryBuilder builder, @Qualifier("productDataSource") DataSource datasource) {
            return builder
                    .dataSource(datasource).properties(jpaProperties.getProperties())
                    .packages("com.product.commons.entities.product.models","com.product.models.product")
                    .persistenceUnit("product")
                    .build();
        }
    
        @Primary
        @Bean(name = "productTransactionManager")
        public PlatformTransactionManager transactionManager(
                @Qualifier("productEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
            return new JpaTransactionManager(entityManagerFactory);
        }
    }

Below is the application.yml content for DB

    spring:
      profiles: mock
      jpa:
        database-platform: org.hibernate.dialect.H2Dialect
        generate-ddl: true
        hibernate:
          ddl-auto: create
      datasource:
        jdbcUrl: jdbc:h2:mem:PRODUCT
        driver-class-name: org.h2.Driver
        maximumPoolSize: 10
        minimumIdle: 5
        idleTimeout: 60000
        maxLifetime: 120000
        leakDetectionThreshold: 180000
        poolName: "product"

SternK
  • 11,649
  • 22
  • 32
  • 46
maker
  • 125
  • 1
  • 1
  • 6

3 Answers3

16

Try to correct this:

@Column(name="OFFSET")
private Long offset;

to

@Column(name="`OFFSET`")
private Long offset;

As OFFSET is reserved keyword you should force Hibernate to quote an identifier in the generated SQL by enclosing the column name in backticks in the mapping document. See this section of hibernate documentation.

SternK
  • 11,649
  • 22
  • 32
  • 46
  • 3
    After looking for a whole day why my table is not created with Hibernate in the H2 database I found this answer. You are awesome! @sternk Adding those ` at my column name `key` finally did the trick. The issue appeared with upgrading to Spring Boot 2.5 and H2 2.1.210 and worked fine previously. – Marcus Mar 11 '22 at 05:56
  • 4
    I had the same problem because of another reserved keyword, a table called `user`. – Islam Hassan Jun 05 '22 at 18:47
  • 3
    this is applicable to table names as well , "User" is a reserved keywork in H2 DB , i resolved the same exception during spring boot project startup it in the same way as described in the answer. – shadow0wolf Jun 18 '22 at 13:06
  • I also had the same issue dealing with a vehicle database, it did not like the `year` attribute ‍♂️ – AussieDev81 Jun 22 '22 at 04:53
1

I faced this same but none of the solutions worked, but if i did the below it worked fine.

Updated the dialect from " spring.jpa.database-platform=org.hibernate.dialect.H2Dialect"

to "spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect"

Procrastinator
  • 2,526
  • 30
  • 27
  • 36
0

Apart from the accepted answer, I want to highlight an alternate way.

We can add "NON_KEYWORDS=OFFSET" in the spring.datasource.url property in properties file.

This works for the reserved keywords used as column name but also in table name. Like, User table name.

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Rishav
  • 1
  • 1