Jhipster 中的 Liquibase 迁移异常

Liquibase migration exception in Jhipster

我有一个包含两个微服务和一个网关的 JHipster 项目。两者都是通过 JHipster 生成的。我正在尝试使用 Spring Cloud Stream with KafkaProjects 微服务向 ChargeCodes 微服务发送一个对象。为此,我在 ProjectResource.java 文件中添加了 Spring Cloud Stream code。根据我的要求,每当创建新项目对象时,Spring Cloud Stream 都应将其发送到 Kafka 主题,第二个微服务中的 Kafka 消费者会使用它。为了简单起见,我在同一个项目中创建了生产者和消费者。当我编译微服务时,出现以下异常。

liquibase.exception.MigrationFailedException: Migration failed for change set config/liquibase/changelog/20180205173557_added_entity_Address.xml::20180205173557-1::jhipster:

我的独立 Spring boot Rest API app with Spring Cloud Stream and Kafka works fine without any issues. I am not sure what's wrong with JHipster code. Code uploaded in github repository

ProjectResource.Java

package com.projects.web.rest;

import com.codahale.metrics.annotation.Timed;
import com.projects.domain.Project;
import com.projects.messaging.Greeting;
import com.projects.repository.ProjectRepository;
import com.projects.web.rest.errors.BadRequestAlertException;
import com.projects.web.rest.util.HeaderUtil;
import com.projects.web.rest.util.PaginationUtil;
import io.github.jhipster.web.util.ResponseUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.net.URI;
import java.net.URISyntaxException;

import java.util.List;
import java.util.Optional;

/**
 * REST controller for managing Project.
 */
@RestController
@RequestMapping("/api")
@EnableBinding(Source.class)
public class ProjectResource
{

    private final Logger log = LoggerFactory.getLogger(ProjectResource.class);

    private static final String ENTITY_NAME = "project";

    private final ProjectRepository projectRepository;

    @Autowired
    private Source source;


    public ProjectResource(ProjectRepository projectRepository)
    {
        this.projectRepository = projectRepository;
    }


    /**
     * POST /projects : Create a new project.
     *
     * @param project
     *            the project to create
     * @return the ResponseEntity with status 201 (Created) and with body the new
     *         project, or with status 400 (Bad Request) if the project has already
     *         an ID
     * @throws URISyntaxException
     *             if the Location URI syntax is incorrect
     */
    @PostMapping("/projects")
    @Timed
    public ResponseEntity<Project> createProject(@Valid @RequestBody Project project) throws URISyntaxException
    {
        log.debug("REST request to save Project : {}", project);
        if (project.getId() != null)
        {
            throw new BadRequestAlertException("A new project cannot already have an ID", ENTITY_NAME, "idexists");
        }
        Project result = projectRepository.save(project);
        source.output().send(MessageBuilder.withPayload(result).build());
        return ResponseEntity.created(new URI("/api/projects/" + result.getId()))
                .headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString())).body(result);
    }

    /**
     * PUT /projects : Updates an existing project.
     *
     * @param project
     *            the project to update
     * @return the ResponseEntity with status 200 (OK) and with body the updated
     *         project, or with status 400 (Bad Request) if the project is not
     *         valid, or with status 500 (Internal Server Error) if the project
     *         couldn't be updated
     * @throws URISyntaxException
     *             if the Location URI syntax is incorrect
     */
    @PutMapping("/projects")
    @Timed
    public ResponseEntity<Project> updateProject(@Valid @RequestBody Project project) throws URISyntaxException
    {
        log.debug("REST request to update Project : {}", project);
        if (project.getId() == null)
        {
            return createProject(project);
        }
        Project result = projectRepository.save(project);
        source.output().send(MessageBuilder.withPayload(result).build());
        return ResponseEntity.ok().headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, project.getId().toString()))
                .body(result);
    }

    /**
     * GET /projects : get all the projects.
     *
     * @param pageable
     *            the pagination information
     * @return the ResponseEntity with status 200 (OK) and the list of projects in
     *         body
     */
    @GetMapping("/projects")
    @Timed
    public ResponseEntity<List<Project>> getAllProjects(Pageable pageable)
    {
        log.debug("REST request to get a page of Projects");
        Page<Project> page = projectRepository.findAll(pageable);
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/projects");
        return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
    }

    /**
     * GET /projects/:id : get the "id" project.
     *
     * @param id
     *            the id of the project to retrieve
     * @return the ResponseEntity with status 200 (OK) and with body the project, or
     *         with status 404 (Not Found)
     */
    @GetMapping("/projects/{id}")
    @Timed
    public ResponseEntity<Project> getProject(@PathVariable Long id)
    {
        log.debug("REST request to get Project : {}", id);
        Project project = projectRepository.findOne(id);
        return ResponseUtil.wrapOrNotFound(Optional.ofNullable(project));
    }

    /**
     * DELETE /projects/:id : delete the "id" project.
     *
     * @param id
     *            the id of the project to delete
     * @return the ResponseEntity with status 200 (OK)
     */
    @DeleteMapping("/projects/{id}")
    @Timed
    public ResponseEntity<Void> deleteProject(@PathVariable Long id)
    {
        log.debug("REST request to delete Project : {}", id);
        projectRepository.delete(id);
        return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, id.toString())).build();
    }
}

异常:

projects-app_1       | 2018-02-06 18:56:24.704 ERROR 6 --- [           main] liquibase                                : classpath:config/liquibase/master.xml: config/liquibase/changelog/20180205173557_added_entity_Address.xml::20180205173557-1::jhipster: Change Set config/liquibase/changelog/20180205173557_added_entity_Address.xml::20180205173557-1::jhipster failed.  Error: Table 'address' already exists [Failed SQL: CREATE TABLE projects.address (id BIGINT AUTO_INCREMENT NOT NULL, street_name VARCHAR(255) NOT NULL, apartment_or_house_number VARCHAR(255) NULL, city VARCHAR(255) NOT NULL, zipcode BIGINT NOT NULL, state VARCHAR(255) NULL, country VARCHAR(255) NULL, CONSTRAINT PK_ADDRESS PRIMARY KEY (id))]
projects-app_1       | 2018-02-06 18:56:24.829  WARN 6 --- [           main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase' defined in class path resource [com/projects/config/DatabaseConfiguration.class]: Invocation of init method failed; nested exception is liquibase.exception.MigrationFailedException: Migration failed for change set config/liquibase/changelog/20180205173557_added_entity_Address.xml::20180205173557-1::jhipster:
projects-app_1       |      Reason: liquibase.exception.DatabaseException: Table 'address' already exists [Failed SQL: CREATE TABLE projects.address (id BIGINT AUTO_INCREMENT NOT NULL, street_name VARCHAR(255) NOT NULL, apartment_or_house_number VARCHAR(255) NULL, city VARCHAR(255) NOT NULL, zipcode BIGINT NOT NULL, state VARCHAR(255) NULL, country VARCHAR(255) NULL, CONSTRAINT PK_ADDRESS PRIMARY KEY (id))]
projects-app_1       | 2018-02-06 18:56:25.380 ERROR 6 --- [           main] o.s.boot.SpringApplication               : Application startup failed
projects-app_1       | 
projects-app_1       | org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase' defined in class path resource [com/projects/config/DatabaseConfiguration.class]: Invocation of init method failed; nested exception is liquibase.exception.MigrationFailedException: Migration failed for change set config/liquibase/changelog/20180205173557_added_entity_Address.xml::20180205173557-1::jhipster:
projects-app_1       |      Reason: liquibase.exception.DatabaseException: Table 'address' already exists [Failed SQL: CREATE TABLE projects.address (id BIGINT AUTO_INCREMENT NOT NULL, street_name VARCHAR(255) NOT NULL, apartment_or_house_number VARCHAR(255) NULL, city VARCHAR(255) NOT NULL, zipcode BIGINT NOT NULL, state VARCHAR(255) NULL, country VARCHAR(255) NULL, CONSTRAINT PK_ADDRESS PRIMARY KEY (id))]
projects-app_1       |  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628)
projects-app_1       |  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
projects-app_1       |  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
projects-app_1       |  at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:306)
projects-app_1       |  at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
projects-app_1       |  at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
projects-app_1       |  at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
projects-app_1       |  at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:296)
projects-app_1       |  at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
projects-app_1       |  at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080)
projects-app_1       |  at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857)
projects-app_1       |  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
projects-app_1       |  at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
projects-app_1       |  at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
projects-app_1       |  at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
projects-app_1       |  at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
projects-app_1       |  at com.projects.ProjectsApp.main(ProjectsApp.java:68)
projects-app_1       |  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
projects-app_1       |  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
projects-app_1       |  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
projects-app_1       |  at java.lang.reflect.Method.invoke(Method.java:498)
projects-app_1       |  at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
projects-app_1       |  at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
projects-app_1       |  at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
projects-app_1       |  at org.springframework.boot.loader.WarLauncher.main(WarLauncher.java:59)
projects-app_1       | Caused by: liquibase.exception.MigrationFailedException: Migration failed for change set config/liquibase/changelog/20180205173557_added_entity_Address.xml::20180205173557-1::jhipster:
projects-app_1       |      Reason: liquibase.exception.DatabaseException: Table 'address' already exists [Failed SQL: CREATE TABLE projects.address (id BIGINT AUTO_INCREMENT NOT NULL, street_name VARCHAR(255) NOT NULL, apartment_or_house_number VARCHAR(255) NULL, city VARCHAR(255) NOT NULL, zipcode BIGINT NOT NULL, state VARCHAR(255) NULL, country VARCHAR(255) NULL, CONSTRAINT PK_ADDRESS PRIMARY KEY (id))]
projects-app_1       |  at liquibase.changelog.ChangeSet.execute(ChangeSet.java:619)
projects-app_1       |  at liquibase.changelog.visitor.UpdateVisitor.visit(UpdateVisitor.java:51)
projects-app_1       |  at liquibase.changelog.ChangeLogIterator.run(ChangeLogIterator.java:79)
projects-app_1       |  at liquibase.Liquibase.update(Liquibase.java:214)
projects-app_1       |  at liquibase.Liquibase.update(Liquibase.java:192)
projects-app_1       |  at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:431)
projects-app_1       |  at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:388)
projects-app_1       |  at io.github.jhipster.config.liquibase.AsyncSpringLiquibase.initDb(AsyncSpringLiquibase.java:94)
projects-app_1       |  at io.github.jhipster.config.liquibase.AsyncSpringLiquibase.afterPropertiesSet(AsyncSpringLiquibase.java:84)
projects-app_1       |  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687)
projects-app_1       |  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)
projects-app_1       |  ... 24 common frames omitted
projects-app_1       | Caused by: liquibase.exception.DatabaseException: Table 'address' already exists [Failed SQL: CREATE TABLE projects.address (id BIGINT AUTO_INCREMENT NOT NULL, street_name VARCHAR(255) NOT NULL, apartment_or_house_number VARCHAR(255) NULL, city VARCHAR(255) NOT NULL, zipcode BIGINT NOT NULL, state VARCHAR(255) NULL, country VARCHAR(255) NULL, CONSTRAINT PK_ADDRESS PRIMARY KEY (id))]
projects-app_1       |  at liquibase.executor.jvm.JdbcExecutor$ExecuteStatementCallback.doInStatement(JdbcExecutor.java:309)
projects-app_1       |  at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:55)
projects-app_1       |  at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:113)
projects-app_1       |  at liquibase.database.AbstractJdbcDatabase.execute(AbstractJdbcDatabase.java:1277)
projects-app_1       |  at liquibase.database.AbstractJdbcDatabase.executeStatements(AbstractJdbcDatabase.java:1259)
projects-app_1       |  at liquibase.changelog.ChangeSet.execute(ChangeSet.java:582)
projects-app_1       |  ... 34 common frames omitted
projects-app_1       | Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'address' already exists
projects-app_1       |  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
projects-app_1       |  at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
projects-app_1       |  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
projects-app_1       |  at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
projects-app_1       |  at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
projects-app_1       |  at com.mysql.jdbc.Util.getInstance(Util.java:408)
projects-app_1       |  at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:943)
projects-app_1       |  at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973)
projects-app_1       |  at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909)
projects-app_1       |  at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527)
projects-app_1       |  at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680)
projects-app_1       |  at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2483)
projects-app_1       |  at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2441)
projects-app_1       |  at com.mysql.jdbc.StatementImpl.executeInternal(StatementImpl.java:845)
projects-app_1       |  at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:745)
projects-app_1       |  at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:95)
projects-app_1       |  at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java)
projects-app_1       |  at liquibase.executor.jvm.JdbcExecutor$ExecuteStatementCallback.doInStatement(JdbcExecutor.java:307)
projects-app_1       |  ... 39 common frames omitted
projects-app_1       | 

乍一看似乎是某些原因导致 DATABASECHANGELOG 中的一行或多行被删除,所以 Liquibase 的事情是创建 table projects.address 的变更集再次获得 运行 , 但 table 已经存在。