我使用Spring Boot 1.4.0.RELEASE
和依赖项中的以下数据库连接器
<!-- runtime dependencies -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
并且有一个实体类,其中包含GenerationType.AUTO
ID生成政策(以下代码未完整)
@Entity
@Table(name = "scanner_run")
public class ScannerRun extends BaseObject {
private Long id;
@Id @GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
public Long getId() {
return this.id;
}
}
使用H2时,插入新实体没有问题
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
Hibernate生成insert into scanner_run (id, completed_ts, repository_id, started_ts, success) values (null, ?, ?, ?, ?)
查询并创建新记录。
然而使用MySQL
spring.datasource.url=jdbc:mysql://localhost/db_dev?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&connectionCollation=utf8_general_ci
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
生成的查询为insert into scanner_run (completed_ts, repository_id, started_ts, success) values (?, ?, ?, ?)
- ID不在查询中 - 失败。
没有其他差异,仅在application.properties
中更改以交换数据库。与早期版本的Hibernate和MySQL连接器相同的代码与MySQL的相同安装一起使用。 MySQL连接器解析为mysql:mysql-connector-java:jar:5.1.39
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(GenericManagerImpl.java:107) at jvr.decrex.scanner.service.impl.ScannerRunManagerImpl.createScan(ScannerRunManagerImpl.java:79) ......... at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) 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(HibernateJpaDialect.java:333) at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244) ......... at jvr.decrex.scanner.dao.jpa.ScannerRunDaoJpa$$EnhancerBySpringCGLIB$$5e6c846a.insert() at jvr.decrex.service.impl.GenericManagerImpl.insert(GenericManagerImpl.java:105) ... 21 common frames omitted Caused by: org.hibernate.exception.GenericJDBCException: could not execute statement at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) .......... at com.sun.proxy.$Proxy126.persist(Unknown Source) at jvr.decrex.dao.jpa.GenericDaoJpa.insert(GenericDaoJpa.java:137) at jvr.decrex.dao.jpa.GenericDaoJpa$$FastClassBySpringCGLIB$$6605cd4e.invoke() at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ... 25 common frames omitted Caused by: java.sql.SQLException: Field 'id' doesn't have a default value at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078) ......... at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2376) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2360) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204) ... 58 common frames omitted
我尝试使用较早版本的5.1.27
mysql-connector-java
版本,该版本适用于旧版本的Hibernate - 它会抛出相同的错误
答案 0 :(得分:1)
您省略了数据库架构,因此需要进行大量的猜测。以下是可以说的: -
AUTO
生成策略意味着JPA提供商可以选择它想要的任何策略。似乎对于MySQL,它使用AUTOINCREMENT
列(相当于IDENTITY
生成策略),对于H2,它可能使用SEQUENCE
(猜测,因为你没有提供如何的细节)。也许你没有为MySQL的PK列定义AUTOINCREMENT?但在这种情况下你不能使用AUTO策略,而且你是。
您可以通过为要部署到的每个数据存储区提供 orm.xml 来处理它,然后您可以根据哪个数据存储区使用不同的生成策略。
或者选择TABLE
生成策略,每次都会插入“id”列而不管数据存储区。
或者选择IDENTITY
(当你使用PK的AUTOINIDEMENT列和PK的H2 IDENTITY列时)因为H2也会使用它(如果你还需要支持另一个数据存储,那么这显然不是一个选项没有这样的IDENTITY
支持。