我正在将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:插入扫描器运行(completed_ts,repository_id,started_ts,成功)值(?,?,?,?)
2016-08-26 14:38:03.967 WARN 32555 --- [myScheduler-1] o.h.engine.jdbc.spi.SqlExceptionHelper:SQL错误:1364,SQLState:HY000
2016-08-26 14:38:03.967错误32555 --- [myScheduler-1] o.h.engine.jdbc.spi.SqlExceptionHelper:字段'id'没有默认值
2016-08-26 14:38:03.979错误32555 --- [myScheduler-1] o.s.s.s.TaskUtils $ LoggingErrorHandler:计划任务发生意外错误。

jvr.decrex.exception.ExecutionError:无法保存ScannerRun {id = null,repository = / jv-ration / projects / jv-ration / deCrex / jvr-decrex /,startedTs = Fri Aug 26 14:38:03 CEST 2016, completeTs = null}
    在jvr.decrex.service.impl.GenericManagerImpl.insert(GenericManagerImpl.java:107)
    在jvr.decrex.scanner.service.impl.ScannerRunManagerImpl.createScan(ScannerRunManagerImpl.java:79)
......
    在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    在java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:617)
    在java.lang.Thread.run(Thread.java:745)
由以下原因引起:org.springframework.orm.jpa.JpaSystemException:无法执行语句;嵌套的异常是org.hibernate.exception.GenericJDBCException:无法执行语句
    在org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:333)
    在org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244)
......
    在jvr.decrex.scanner.dao.jpa.ScannerRunDaoJpa $$ EnhancerBySpringCGLIB $$ 5e6c846a.insert()
    在jvr.decrex.service.impl.GenericManagerImpl.insert(GenericManagerImpl.java:105)
    ...省略了21个通用框架
引起原因:org.hibernate.exception.GenericJDBCException:无法执行语句
    在org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)
    在org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109)
    在org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95)
..........
    在com.sun.proxy。$ Proxy126.persist(未知来源)
    在jvr.decrex.dao.jpa.GenericDaoJpa.insert(GenericDaoJpa.java:137)
    在jvr.decrex.dao.jpa.GenericDaoJpa $$ FastClassBySpringCGLIB $$ 6605cd4e.invoke()
    在org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    在org.springframework.aop.framework.CglibAopProxy $ CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720)
    在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    在org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    ...省略了25个通用框架
原因:java.sql.SQLException:字段“ id”没有默认值
    在com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078)
......
    在com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2376)
    在com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2360)
    在org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)
    ...省略了58个通用框架


我尝试使用旧版本的5.1.27 mysql-connector-java,该版本可与旧版本的Hibernate配合使用-抛出相同的错误

最佳答案

您省略了数据库模式,因此要进行大量的猜测。以下是可以说的:

AUTO生成策略意味着JPA提供者可以选择所需的任何内容作为策略。看来,对于MySQL,它使用AUTOINCREMENT列(相当于IDENTITY生成策略),对于H2,它可能使用SEQUENCE(猜测,因为您未提供具体方法)。也许您没有为MySQL的PK列定义AUTOINCREMENT?但是在那种情况下,您不能使用AUTO策略,而是可以。

您可以通过为要部署到的每个数据存储都拥有一个orm.xml来处理它,然后可以根据哪个数据存储区使用不同的生成策略。

或者,选择TABLE生成策略,并且无论数据存储如何,每次都会插入“ id”列。

或选择IDENTITY(当您将MySQL AUTOINCREMENT列用作PK,将H2 IDENTITY列用作PK时),因为H2还将使用它(显然,如果您还需要支持没有此类支持)。

10-05 21:02
查看更多