H2 和 Oracle 兼容性问题
Posted
技术标签:
【中文标题】H2 和 Oracle 兼容性问题【英文标题】:H2 and Oracle Compatiability issues 【发布时间】:2013-12-11 18:31:23 【问题描述】:我在使用 Flyway 和 H2 数据库执行以下脚本时遇到问题。我认为这是一个 Oracle 兼容性问题,但我使用的是正确模式的 H2。该脚本用于在生产中构建我的表,但我想使用内存数据库进行测试。下面的设置和错误。如果可能的话,我不想重写内存数据库的脚本。
Jdbc.properties
jdbc.driver=org.h2.Driver
jdbc.url=jdbc:h2:file:target/firmsoftDB;MODE=Oracle
jdbc.username=sa
jdbc.password=
Sql 脚本
CREATE TABLE USER_INFO
(
USER_INFO_ID NUMBER NOT NULL,
USER_NAME VARCHAR2(32 BYTE) NOT NULL,
EMAIL VARCHAR2(320 BYTE) NULL,
LAST_NAME VARCHAR2(32 BYTE) NOT NULL,
FIRST_NAME VARCHAR2(32 BYTE) NOT NULL,
LAST_LOGIN TIMESTAMP(6) NULL,
USER_TYPE VARCHAR2(32 BYTE) NULL,
USER_CN VARCHAR2(32 BYTE) NULL,
SOURCE_DIRECTORY VARCHAR2(15 BYTE) NULL,
PRIMARY_PHONE VARCHAR2(32 BYTE) NULL,
ALT_PHONE VARCHAR2(32 BYTE) NULL,
CREATED_BY NUMBER NOT NULL,
CREATED_DATE TIMESTAMP(6) NOT NULL,
UPDATED_BY NUMBER NOT NULL,
UPDATED_DATE TIMESTAMP(6) NOT NULL
)
LOGGING
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;
pom.xml
<profiles>
<profile>
<id>h2-test</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<flyway.locations>db/migration</flyway.locations>
</systemPropertyVariables>
<threadCount>1</threadCount>
</configuration>
<goals>
<goal>test</goal>
</goals>
<executions>
</executions>
</plugin>
<plugin>
<groupId>com.googlecode.flyway</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<!-- <url>jdbc:hsqldb:file:target/firmsoftDB;sql.syntax_ora=true</url> -->
<!-- <url>jdbc:hsqldb:mem:firmsoftDB;sql.syntax_ora=true</url> -->
<url>jdbc:h2:file:target/firmsoftDB;MODE=Oracle</url>
<!-- <url>jdbc:derby:\temp\db\FAQ\db</url> -->
</configuration>
</plugin>
</plugins>
</build>
</profile>
上下文
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd">
<!-- Needed for system properties replacement -->
<!-- Following will only work with spring 3 -->
<context:property-placeholder location="classpath*:jdbc.properties,classpath*:flyway.default.properties,classpath*:flyway.properties"
ignore-resource-not-found="true"
system-properties-mode="OVERRIDE"/>
<!-- flyway part -->
<bean id="flyway" class="com.googlecode.flyway.core.Flyway" depends-on="dataSourceRef">
<property name="dataSource" ref="dataSourceRef"/>
<property name="locations" value="$flyway.locations"/>
</bean>
<bean id="dataSourceRef" name="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"><value>$jdbc.driver</value></property>
<property name="url"><value>$jdbc.url</value></property>
<property name="username"><value>$jdbc.username</value></property>
<property name="password"><value>$jdbc.password</value></property>
<property name="maxActive" value="-1"/>
</bean>
堆栈跟踪
[ERROR] Failed to execute goal com.googlecode.flyway:flyway-maven-plugin:2.2.1:migrate (default-cli) on project flyway-test: com.googlecode.flyway.core.api.FlywayException: Migration of schema "PUBLIC" to version 1 failed! Please restore backups and roll back database and code! Syntax error in SQL statement "CREATE TABLE USER_INFO
[ERROR] (
[ERROR] USER_INFO_ID NUMBER NOT NULL,
[ERROR] USER_NAME VARCHAR2(32 BYTE[*]) NOT NULL,
[ERROR] EMAIL VARCHAR2(320 BYTE) NULL,
[ERROR] LAST_NAME VARCHAR2(32 BYTE) NOT NULL,
[ERROR] FIRST_NAME VARCHAR2(32 BYTE) NOT NULL,
[ERROR] LAST_LOGIN TIMESTAMP(6) NULL,
[ERROR] USER_TYPE VARCHAR2(32 BYTE) NULL,
[ERROR] USER_CN VARCHAR2(32 BYTE) NULL,
[ERROR] SOURCE_DIRECTORY VARCHAR2(15 BYTE) NULL,
[ERROR] PRIMARY_PHONE VARCHAR2(32 BYTE) NULL,
[ERROR] ALT_PHONE VARCHAR2(32 BYTE) NULL,
[ERROR] CREATED_BY NUMBER NOT NULL,
[ERROR] CREATED_DATE TIMESTAMP(6) NOT NULL,
[ERROR] UPDATED_BY NUMBER NOT NULL,
[ERROR] UPDATED_DATE TIMESTAMP(6) NOT NULL
[ERROR] )
[ERROR] LOGGING
[ERROR] NOCOMPRESS
[ERROR] NOCACHE
[ERROR] NOPARALLEL
[ERROR] MONITORING"; expected "K, M, G, CHAR, )"; SQL statement:
[ERROR] CREATE TABLE USER_INFO
[ERROR] (
[ERROR] USER_INFO_ID NUMBER NOT NULL,
[ERROR] USER_NAME VARCHAR2(32 BYTE) NOT NULL,
[ERROR] EMAIL VARCHAR2(320 BYTE) NULL,
[ERROR] LAST_NAME VARCHAR2(32 BYTE) NOT NULL,
[ERROR] FIRST_NAME VARCHAR2(32 BYTE) NOT NULL,
[ERROR] LAST_LOGIN TIMESTAMP(6) NULL,
[ERROR] USER_TYPE VARCHAR2(32 BYTE) NULL,
[ERROR] USER_CN VARCHAR2(32 BYTE) NULL,
[ERROR] SOURCE_DIRECTORY VARCHAR2(15 BYTE) NULL,
[ERROR] PRIMARY_PHONE VARCHAR2(32 BYTE) NULL,
[ERROR] ALT_PHONE VARCHAR2(32 BYTE) NULL,
[ERROR] CREATED_BY NUMBER NOT NULL,
[ERROR] CREATED_DATE TIMESTAMP(6) NOT NULL,
[ERROR] UPDATED_BY NUMBER NOT NULL,
[ERROR] UPDATED_DATE TIMESTAMP(6) NOT NULL
[ERROR] )
[ERROR] LOGGING
[ERROR] NOCOMPRESS
[ERROR] NOCACHE
[ERROR] NOPARALLEL
[ERROR] MONITORING [42001-174]
[ERROR] -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal com.googlecode.flyway:flyway-maven-plugin:2.2.1:migrate (default-cli) on project flyway-test: com.googlecode.flyway.core.api.FlywayException: Migration of schema "PUBLIC" to version 1 failed! Please restore backups and roll back database and code!
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:217)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:319)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
Caused by: org.apache.maven.plugin.MojoExecutionException: com.googlecode.flyway.core.api.FlywayException: Migration of schema "PUBLIC" to version 1 failed! Please restore backups and roll back database and code!
at com.googlecode.flyway.maven.AbstractFlywayMojo.execute(AbstractFlywayMojo.java:253)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
... 19 more
Caused by: org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "CREATE TABLE USER_INFO
(
USER_INFO_ID NUMBER NOT NULL,
USER_NAME VARCHAR2(32 BYTE[*]) NOT NULL,
EMAIL VARCHAR2(320 BYTE) NULL,
LAST_NAME VARCHAR2(32 BYTE) NOT NULL,
FIRST_NAME VARCHAR2(32 BYTE) NOT NULL,
LAST_LOGIN TIMESTAMP(6) NULL,
USER_TYPE VARCHAR2(32 BYTE) NULL,
USER_CN VARCHAR2(32 BYTE) NULL,
SOURCE_DIRECTORY VARCHAR2(15 BYTE) NULL,
PRIMARY_PHONE VARCHAR2(32 BYTE) NULL,
ALT_PHONE VARCHAR2(32 BYTE) NULL,
CREATED_BY NUMBER NOT NULL,
CREATED_DATE TIMESTAMP(6) NOT NULL,
UPDATED_BY NUMBER NOT NULL,
UPDATED_DATE TIMESTAMP(6) NOT NULL
)
LOGGING
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING"; expected "K, M, G, CHAR, )"; SQL statement:
CREATE TABLE USER_INFO
(
USER_INFO_ID NUMBER NOT NULL,
USER_NAME VARCHAR2(32 BYTE) NOT NULL,
EMAIL VARCHAR2(320 BYTE) NULL,
LAST_NAME VARCHAR2(32 BYTE) NOT NULL,
FIRST_NAME VARCHAR2(32 BYTE) NOT NULL,
LAST_LOGIN TIMESTAMP(6) NULL,
USER_TYPE VARCHAR2(32 BYTE) NULL,
USER_CN VARCHAR2(32 BYTE) NULL,
SOURCE_DIRECTORY VARCHAR2(15 BYTE) NULL,
PRIMARY_PHONE VARCHAR2(32 BYTE) NULL,
ALT_PHONE VARCHAR2(32 BYTE) NULL,
CREATED_BY NUMBER NOT NULL,
CREATED_DATE TIMESTAMP(6) NOT NULL,
UPDATED_BY NUMBER NOT NULL,
UPDATED_DATE TIMESTAMP(6) NOT NULL
)
LOGGING
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING [42001-174]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:332)
at org.h2.message.DbException.getSyntaxError(DbException.java:197)
at org.h2.command.Parser.getSyntaxError(Parser.java:504)
at org.h2.command.Parser.read(Parser.java:2867)
at org.h2.command.Parser.parseColumnWithType(Parser.java:3788)
at org.h2.command.Parser.parseColumnForTable(Parser.java:3603)
at org.h2.command.Parser.parseCreateTable(Parser.java:5354)
at org.h2.command.Parser.parseCreate(Parser.java:3890)
at org.h2.command.Parser.parsePrepared(Parser.java:334)
at org.h2.command.Parser.parse(Parser.java:289)
at org.h2.command.Parser.parse(Parser.java:265)
at org.h2.command.Parser.prepareCommand(Parser.java:226)
at org.h2.engine.Session.prepareLocal(Session.java:437)
at org.h2.engine.Session.prepareCommand(Session.java:380)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1138)
at org.h2.jdbc.JdbcStatement.executeInternal(JdbcStatement.java:168)
at org.h2.jdbc.JdbcStatement.execute(JdbcStatement.java:156)
at com.googlecode.flyway.core.dbsupport.JdbcTemplate.executeStatement(JdbcTemplate.java:230)
at com.googlecode.flyway.core.dbsupport.SqlScript.execute(SqlScript.java:89)
at com.googlecode.flyway.core.resolver.sql.SqlMigrationExecutor.execute(SqlMigrationExecutor.java:72)
at com.googlecode.flyway.core.command.DbMigrate$2.doInTransaction(DbMigrate.java:252)
at com.googlecode.flyway.core.command.DbMigrate$2.doInTransaction(DbMigrate.java:250)
at com.googlecode.flyway.core.util.jdbc.TransactionTemplate.execute(TransactionTemplate.java:56)
at com.googlecode.flyway.core.command.DbMigrate.applyMigration(DbMigrate.java:250)
at com.googlecode.flyway.core.command.DbMigrate.access$700(DbMigrate.java:47)
at com.googlecode.flyway.core.command.DbMigrate$1.doInTransaction(DbMigrate.java:189)
at com.googlecode.flyway.core.command.DbMigrate$1.doInTransaction(DbMigrate.java:138)
at com.googlecode.flyway.core.util.jdbc.TransactionTemplate.execute(TransactionTemplate.java:56)
at com.googlecode.flyway.core.command.DbMigrate.migrate(DbMigrate.java:137)
at com.googlecode.flyway.core.Flyway$1.execute(Flyway.java:872)
at com.googlecode.flyway.core.Flyway$1.execute(Flyway.java:819)
at com.googlecode.flyway.core.Flyway.execute(Flyway.java:1200)
at com.googlecode.flyway.core.Flyway.migrate(Flyway.java:819)
at com.googlecode.flyway.maven.MigrateMojo.doExecuteWithMigrationConfig(MigrateMojo.java:159)
at com.googlecode.flyway.maven.AbstractMigrationLoadingMojo.doExecute(AbstractMigrationLoadingMojo.java:151)
at com.googlecode.flyway.maven.AbstractFlywayMojo.execute(AbstractFlywayMojo.java:251)
... 21 more
[ERROR]
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
【问题讨论】:
您真的需要将 varchar2 设为字节吗?您可以像这样指定大小:USER_NAME VARCHAR2(32)
试试看。对于其他列也是如此。
当前形式的此架构是当前正在使用的架构,我不想更改此架构。我希望我在测试中使用的架构能够反映生产中的架构。
你能把所有的堆栈跟踪吗?此外,根据 oracle 文档,不推荐使用 MONITORING。
添加了堆栈跟踪,我想我刚刚遇到了 H2 和 HSQLDB 的限制,如果我用 VARCHAR2 替换 VARCHAR 并删除以下关键字 LOGGING NOCOMPRESS NOCACHE NOPARALLEL MONITORING
【参考方案1】:
H2 无法识别语法
VARCHAR2(32 BYTE)
把这个改成
VARCHAR2(32)
...它仍然可以在 oracle 中工作,并且至少会消除您在 H2 中的第一个错误。
【讨论】:
小问题:如果您没有明确指定 BYTE 或 CHAR,Oracle 的解释将取决于默认为 BYTE 的 NLS_LENGTH_SEMANTICS 的设置,以实现向后兼容性,但可能为最好由您的 DBA 设置为 CHAR,因为在处理字符串时后一种设置更有意义。【参考方案2】:简答
Oracle 是一个庞大的软件,您不能指望小型嵌入式数据库 100% 兼容。
长答案
兼容模式
如文档所述,for certain features, this database can emulate the behavior of specific databases。但是,只有一小部分数据库之间的差异以这种方式实现。此列表已记录在案。
兼容性
如文档所述,H2 is (up to a certain point) compatible to other databases,例如 HSQLDB、mysql 和 PostgreSQL。 H2 在某些领域是不兼容的。
所有数据库引擎的行为都略有不同。在可能的情况下,H2 支持 ANSI SQL 标准,并尝试与其他数据库兼容。不过还是有区别的。
【讨论】:
以上是关于H2 和 Oracle 兼容性问题的主要内容,如果未能解决你的问题,请参考以下文章
用于与 postgresql 在内存中兼容 h2 的 Spring Boot 属性
使用 H2、JPA 注释和 Hibernate 问题的一对多关联