【问题标题】:Custom property in liquibase (after migration to newer version) causes failure in Spring bootliquibase 中的自定义属性(迁移到较新版本后)导致 Spring 启动失败
【发布时间】:2019-12-17 11:16:18
【问题描述】:

我不得不在 Spring-boot maven 项目中迁移到更新版本的 Liquibase 核心,之后,我得到了一个 ArrayIndexOutOfBoundsException。

属性定义:

<property dbms="db2,derby,mysql,h2,mssql" name="autoid" value="BIGINT"/>
<property dbms="oracle" name="autoid" value="BIGINT" />
<property dbms="postgresql" name="autoid" value="SERIAL"/>

抛出异常

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase' defined in class path resource [com/unymira/kfirst/application/config/DatabaseManagementConfig.class]: Invocation of init method failed; nested exception is java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1694)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:573)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:762)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:881)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:386)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1242)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1230)
    at com.unymira.kfirst.application.ApplicationLauncher.main(ApplicationLauncher.java:55)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1
    at liquibase.datatype.DataTypeFactory.fromDescription(DataTypeFactory.java:251)
    at liquibase.change.core.CreateTableChange.generateStatements(CreateTableChange.java:70)
    at liquibase.change.AbstractChange.generateStatementsVolatile(AbstractChange.java:287)
    at liquibase.change.AbstractChange.warn(AbstractChange.java:358)
    at liquibase.changelog.visitor.ValidatingVisitor.visit(ValidatingVisitor.java:110)
    at liquibase.changelog.ChangeLogIterator.run(ChangeLogIterator.java:83)
    at liquibase.changelog.DatabaseChangeLog.validate(DatabaseChangeLog.java:284)
    at liquibase.Liquibase.update(Liquibase.java:198)
    at liquibase.Liquibase.update(Liquibase.java:179)
    at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:366)
    at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:314)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1753)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1690)
    ... 21 common frames omitted

属性使用示例

<column autoIncrement="true" name="id" type="${autoid}">
<constraints nullable="false" primaryKey="true" primaryKeyName="${db_prefix}instancepk" />
</column>

我不得不提一下,这段代码是以前的代码,对于旧的 liquibase 没有任何问题。

有人对我做错了什么有建议吗?

【问题讨论】:

  • 听起来可能是一个错误。您介意在liquibase.jira.com 提交更详细的错误报告(包括旧版本号和新版本号)吗?
  • 嗨@SteveDonie,感谢您的回答。我即将为其创建一个 Jira 问题,其中所有内容都已指定。我在那里做了一些调试,发现问题只发生在 MySQL (MariaDB) 数据库上。我们尝试在 H2、MSSQL、Postgres 上初始化相同的数据库架构,但没有出现任何错误。
  • @SteveDonie JIRA 任务已创建 - liquibase.jira.com/browse/CORE-3546
  • 您没有多个数据源吗?
  • @florin 我认为 liquibase 中存在错误。请参阅 SteveDonie 的回复。有一种解决方法。您可以在测试资源上声明测试模式并使用数据库引擎支持的原生类型。

标签: java mysql database spring liquibase


【解决方案1】:

这是一个不太优雅的解决方法,而这个错误是开放的。

免责声明:这会给您的测试增加一点开销,并且可能并不适合所有人。您需要手动更新您的测试架构。

假设您在 liquibase 迁移步骤上有以下数据库:

CREATE TABLE foo(
  id text PRIMARY KEY,
  name text not null,
  hobbies text[] not null,
  locals jsonb,
  status boolean not null default false,
  date_time_updated timestamp,
  date_time_created timestamp NOT NULL
);

在您的 SpringBoot 休息资源中的测试/资源上,您可以使用以下内容创建一个 testschema.sql:

CREATE TABLE foo(
  id character varying(255) DEFAULT RANDOM_UUID() NOT NULL,
  name character varying(255) NOT NULL,
  hobbies ARRAY NOT NULL,
  locals json NOT NULL,
  status boolean,
  date_time_updated timestamp without time zone,
  date_time_created timestamp without time zone NOT NULL
);

爱好是:

<property name="json_type" value="json" dbms="postgresql"/>

我在我的实体中拥有

@Table(name = "foo")
@TypeDef(name = "json", typeClass = JsonBinaryType.class)
@TypeDef(
  name = "string-array",
  typeClass = StringArrayType.class
)
public class Foo {
...
@Type(type = "string-array")
@Column(name = "hobbies", columnDefinition = "text[]")
private String[] hobbies;

@Type(type = "json")
@Column(name = "locals", columnDefinition = "json")
private JsonNode locals;

然后你可以简单地为你的 repo 写一个@DataJpaTest:

@ExtendWith(SpringExtension.class)
@DataJpaTest
@TestPropertySource(properties = {
  "spring.jpa.hibernate.ddl-auto=validate"
})
public class TestFooRepository {

  @Autowired
  private DataSource dataSource;
  @Autowired
  private JdbcTemplate jdbcTemplate;
  @Autowired
  private EntityManager entityManager;
  @Autowired
  private FooRepository fooRepository;

  @Test
  void injectedComponentsAreNotNull() {
    assertThat(dataSource).isNotNull();
    assertThat(jdbcTemplate).isNotNull();
    assertThat(entityManager).isNotNull();
    assertThat(notificationRepository).isNotNull();
  }

  @Test
  public void testShouldSaveTheCorrectObject() throws JsonProcessingException {
    Foo expected = buildTestFoo();
    fooRepository.save(expected);
    final Optional<Foo> actual = notificationRepository.findById("<foo_id>");
    Assert.assertNotNull(actual);
    Assert.assertTrue(actual.isPresent());

    Assert.assertEquals(expected.getId(), actual.get().getId());
  }
}

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    就我而言,这是因为从 3.6.0 开始,在 MariaDB 上运行时我必须使用 dbms="mariadb",而在之前的版本中它曾经被标识为 "mysql"。

    由此更改引起:https://github.com/liquibase/liquibase/commit/7fb10ed7ae599cab585d4a6a4ec891ad7b91ecf1#diff-a07fbaf7b19fd286fef2e684648d5159

    【讨论】:

      【解决方案3】:

      我在使用 Open JDK 11 时遇到了类似的问题。切换到 Oracle JDK 11 后,liquibase:diff 运行正常。很奇怪。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-12
        • 2011-03-06
        • 1970-01-01
        • 1970-01-01
        • 2011-02-15
        • 2019-04-28
        • 1970-01-01
        • 2022-08-06
        相关资源
        最近更新 更多