Viktor Viktor - 11 months ago 107
MySQL Question

How to force Hibernate to add ID column to insert query?

I'm using Spring Boot

with the following DB connectors in dependencies

<!-- runtime dependencies -->

And there is an entity class with
policy for ID generation (code below is not complete)

@Table(name = "scanner_run")
public class ScannerRun extends BaseObject {

private Long id;

@Id @GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
public Long getId() {

There are not problems with insert of new entities, when H2 is used


Hibernate generates
insert into scanner_run (id, completed_ts, repository_id, started_ts, success) values (null, ?, ?, ?, ?)
query and new record is created.

However with MySQL


the generated query is
insert into scanner_run (completed_ts, repository_id, started_ts, success) values (?, ?, ?, ?)
- ID is not in the query - and it fails.

There are no other differences, only change in
to swapp the database. The same code with older versions of Hibernate and MySQL connector works with the same installation of MySQL. MySQL connector resolves to

Can you spot anything wrong?

The exact messages and exception in the logs are:

2016-08-26 14:38:03.964 DEBUG 32555 --- [ myScheduler-1] org.hibernate.SQL : insert into scanner_run (completed_ts, repository_id, started_ts, success) values (?, ?, ?, ?)
2016-08-26 14:38:03.967 WARN 32555 --- [ myScheduler-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1364, SQLState: HY000
2016-08-26 14:38:03.967 ERROR 32555 --- [ myScheduler-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Field 'id' doesn't have a default value
2016-08-26 14:38:03.979 ERROR 32555 --- [ myScheduler-1] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task.

jvr.decrex.exception.ExecutionError: Failed to save ScannerRun{id=null, repository=/jv-ration/projects/jv-ration/deCrex/jvr-decrex/, startedTs=Fri Aug 26 14:38:03 CEST 2016, completedTs=null}
at jvr.decrex.service.impl.GenericManagerImpl.insert(
at jvr.decrex.scanner.service.impl.ScannerRunManagerImpl.createScan(
at java.util.concurrent.ThreadPoolExecutor.runWorker(
at java.util.concurrent.ThreadPoolExecutor$
Caused by: org.springframework.orm.jpa.JpaSystemException: could not execute statement; nested exception is org.hibernate.exception.GenericJDBCException: could not execute statement
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(
at jvr.decrex.scanner.dao.jpa.ScannerRunDaoJpa$$EnhancerBySpringCGLIB$$5e6c846a.insert()
at jvr.decrex.service.impl.GenericManagerImpl.insert(
... 21 common frames omitted
Caused by: org.hibernate.exception.GenericJDBCException: could not execute statement
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(
at com.sun.proxy.$Proxy126.persist(Unknown Source)
at jvr.decrex.dao.jpa.GenericDaoJpa.insert(
at jvr.decrex.dao.jpa.GenericDaoJpa$$FastClassBySpringCGLIB$$6605cd4e.invoke()
at org.springframework.cglib.proxy.MethodProxy.invoke(
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
... 25 common frames omitted
Caused by: java.sql.SQLException: Field 'id' doesn't have a default value
at com.mysql.jdbc.SQLError.createSQLException(
at com.mysql.jdbc.PreparedStatement.executeUpdate(
at com.mysql.jdbc.PreparedStatement.executeUpdate(
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(
... 58 common frames omitted

I tried using older
version of
, which works with older version of Hibernate - it throws the same error

Answer Source

You omit the database schema(s) so an amount of guesswork is to be made. The following is what can be said :-

AUTO generation strategy means the JPA provider can choose whatever it wants as the strategy. It seems that for MySQL it uses AUTOINCREMENT columns (equivalent to IDENTITY generation strategy), and for H2 it maybe uses a SEQUENCE (guessing since you provide no details of how). Maybe you don't have AUTOINCREMENT defined for the PK column with MySQL? but you can't use AUTO strategy in that case, and you are.

You could handle it by having an orm.xml for each datastore you will deploy to, and then you can use different generation strategies based on which datastore.

Alternatively choose TABLE generation strategy and it will insert the "id" column each time regardless of the datastore.

Or choose IDENTITY (when you use MySQL AUTOINCREMENT column for PK, and H2 IDENTITY column for PK) since H2 would then use that also (clearly this is not an option if you also need to support another datastore that has no such IDENTITY support).