Spring boot、JPA、Hibernate 和 H2 DB 测试 - 序列不起作用 - 意外的代码路径”;SQL 语句:调用 seq_my_jobs [50000-193] 的下一个值
Posted
技术标签:
【中文标题】Spring boot、JPA、Hibernate 和 H2 DB 测试 - 序列不起作用 - 意外的代码路径”;SQL 语句:调用 seq_my_jobs [50000-193] 的下一个值【英文标题】:Spring boot, JPA, Hibernate and H2 DB tests - Sequence not working - Unexpected code path"; SQL statement: call next value for seq_my_jobs [50000-193] 【发布时间】:2017-06-28 20:37:03 【问题描述】:我的 Spring Boot 应用上有一个实体:
@Entity
@Table(name = "MY_JOBS")
public class InstallationJobEntity
@GeneratedValue(generator="SEQUENCE_GENERATOR", strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name="SEQUENCE_GENERATOR",sequenceName="SEQ_MY_JOBS", allocationSize=100)
@Id
@Column(name = "ID")
private Long id;
@Column(name = "CONFIGURATION_DATA")
@Lob
private String configurationData;
public Long getId()
return id;
public String getConfigurationData()
return configurationData;
public void setId(Long id)
this.id = id;
public void setConfigurationData(String configurationData)
this.configurationData = configurationData;
对于我的测试,我在 application.yml 上配置 H2 DB:
spring:
jpa:
database: H2
show-sql: true
hibernate:
ddl-auto: none
properties:
hibernate:
dialect: common.H2Dialect
datasource:
initialize: true
schema: schema.sql
data: data.sql
url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;Mode=Oracle;DATABASE_TO_UPPER=false;
username:
platform: h2
driver-class-name: org.h2.Driver
testWhileIdle: true
validationQuery: SELECT 1 from DUAL
在 schema.sql 上,我创建了表和序列(我直接使用 JdbcTemplate 对其进行了测试,它正在工作)
在运行我的测试时,我得到了这个异常:
2017-02-10 15:07:47.764 ERROR 22618 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : General error: "java.lang.RuntimeException: Unexpected code path"; SQL statement:
call next value for seq_my_jobs [50000-193]
org.springframework.orm.jpa.JpaSystemException: could not extract ResultSet; nested exception is org.hibernate.exception.GenericJDBCException: could not extract ResultSet
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:333)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:491)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy121.save(Unknown Source)
at softwaremanagement.services.dao.DAOServiceImpl.createInstallationJob(DAOServiceImpl.java:65)
at softwaremanagement.services.BLServiceImpl.installationRequest(BLServiceImpl.java:51)
at softwaremanagement.orchestration.actors.BLIntegrationTest.integrationWithMockGWFromBLServiceLevel(BLIntegrationTest.java:88)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: org.hibernate.exception.GenericJDBCException: could not extract ResultSet
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 org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:79)
at org.hibernate.id.SequenceGenerator.generateHolder(SequenceGenerator.java:116)
at org.hibernate.id.SequenceHiLoGenerator$1.getNextValue(SequenceHiLoGenerator.java:71)
at org.hibernate.id.enhanced.LegacyHiLoAlgorithmOptimizer.generate(LegacyHiLoAlgorithmOptimizer.java:60)
at org.hibernate.id.SequenceHiLoGenerator.generate(SequenceHiLoGenerator.java:67)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:101)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:775)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:748)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:753)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1146)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298)
at com.sun.proxy.$Proxy116.persist(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:506)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:503)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:488)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:460)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
... 42 more
Caused by: org.h2.jdbc.JdbcSQLException: General error: "java.lang.RuntimeException: Unexpected code path"; SQL statement:
call next value for seq_my_jobs [50000-193]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:168)
at org.h2.message.DbException.convert(DbException.java:295)
at org.h2.command.Command.executeQuery(Command.java:213)
at org.h2.jdbc.JdbcPreparedStatement.executeQuery(JdbcPreparedStatement.java:110)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:70)
... 77 more
Caused by: java.lang.RuntimeException: Unexpected code path
at org.h2.message.DbException.throwInternalError(DbException.java:242)
at org.h2.message.DbException.throwInternalError(DbException.java:255)
at org.h2.engine.Session.addLock(Session.java:842)
at org.h2.mvstore.db.MVTable.doLock2(MVTable.java:254)
at org.h2.mvstore.db.MVTable.doLock1(MVTable.java:202)
at org.h2.mvstore.db.MVTable.lock(MVTable.java:167)
at org.h2.engine.Database.lockMeta(Database.java:909)
at org.h2.engine.Database.removeSchemaObject(Database.java:1842)
at org.h2.table.Table.removeChildrenAndResources(Table.java:530)
at org.h2.table.TableView.removeChildrenAndResources(TableView.java:414)
at org.h2.engine.Session.cleanTempTables(Session.java:948)
at org.h2.engine.Session.commit(Session.java:643)
at org.h2.schema.Sequence.flush(Sequence.java:302)
at org.h2.schema.Sequence.getNext(Sequence.java:269)
at org.h2.expression.SequenceValue.getValue(SequenceValue.java:30)
at org.h2.command.dml.Call.query(Call.java:65)
at org.h2.command.CommandContainer.query(CommandContainer.java:110)
at org.h2.command.Command.executeQuery(Command.java:201)
... 79 more
主要问题是: 原因:org.h2.jdbc.JdbcSQLException: 一般错误:“java.lang.RuntimeException: Unexpected code path”; SQL 语句: 调用 seq_my_jobs [50000-193] 的下一个值
我还尝试使用(所有注释的代码都不能正常工作......)实现我自己的 H2 方言:
public class H2Dialect extends org.hibernate.dialect.H2Dialect
@Override
public String getSequenceNextValString(String sequenceName)
// return "SELECT "+ sequenceName + ".nextval";
// return "SELECT "+sequenceName+".nextval from DUAL";
// return "SELECT "+"NEXTVAL('"+sequenceName+"')";
return "SELECT SEQ_MY_JOBS.nextVal from DUAL";
有什么想法吗?
【问题讨论】:
【参考方案1】:由于您在 Oracle 兼容模式 Mode=Oracle
下运行 H2,因此请使用 oracle 方言:
properties:
hibernate:
dialect: org.hibernate.dialect.Oracle10gDialect
【讨论】:
刚刚试了一下——我也遇到了同样的异常: 原因:org.h2.jdbc.JdbcSQLException:一般错误:“java.lang.RuntimeException:意外的代码路径”; SQL语句:select seq_my_jobs.nextval from dual [50000-193] 我赌的是区分大小写的匹配。请删除DATABASE_TO_UPPER=false
并重试。 H2 文档说将其设置为 false 是实验性的。
已经试过了 - 出现同样的异常。我觉得这与 H2 何时创建序列或何时允许开始使用它有关。尝试运行查询时: select seq_my_jobs.nextval from dual with jdbcTemplate.queryForRowSet 它不起作用,直到我使用 jdbcTemplate.queryForInt 运行它,它返回一个结果。之后 - 它也与 jdbcTemplate.queryForRowSet 一起使用以上是关于Spring boot、JPA、Hibernate 和 H2 DB 测试 - 序列不起作用 - 意外的代码路径”;SQL 语句:调用 seq_my_jobs [50000-193] 的下一个值的主要内容,如果未能解决你的问题,请参考以下文章
制作多个 EntityManager(Spring-Boot-JPA、Hibernate、MSSQL)
Spring Boot / JPA / Hibernate,如何根据 Spring 配置文件切换数据库供应商?
Spring boot之 JPA/Hibernate/Spring Data
Spring Boot JPA Hibernate - 以毫秒精度存储日期
当加载 spring-boot 和 spring-data-jpa 时,Hibernate 无法加载 JPA 2.1 Converter