Neste artigo, discutirei o uso do utilitário
Liquibase nos aplicativos Spring Boot para
versionar a estrutura de um banco de dados relacional e migrar essa estrutura de uma versão para outra. Na primeira parte, analisaremos o exemplo básico e, na segunda, falaremos sobre o uso do
liquibase-mave-plugin para reverter as alterações e gerar automaticamente scripts comparando as estruturas do banco de dados.
Vamos começar criando o aplicativo mais simples no Spring Boot + JPA (Hibernate). O
Spring Initializr nos ajudará com isso. Nas dependências, selecione JPA, MySQL e Web. O Liquibase também pode ser conectado nesta etapa, mas para uma melhor compreensão, faremos isso mais tarde manualmente.
Crie a base do aplicativo
Adicionamos uma classe de entidade ao nosso aplicativo, além de um repositório e um controlador REST para trabalhar com ele. Por concretude, armazenaremos informações sobre usuários na entidade criada.
@Entity @Table(name = "users") public class User implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Long id; @Column(name = "username", unique = true, nullable = false) private String userName; @Column(name = "password", nullable = false) private String password; @Column(name = "first_name") private String firstName; @Column(name = "last_name") private String lastName; @Column(name = "email") private String email;
Spring Data torna o código do repositório extremamente conciso
public interface UserRepository extends JpaRepository<User, Long> { }
Controlador REST que exibirá todo o conteúdo da tabela do usuário
@RestController public class UserController { private UserRepository userRepository; @Autowired public UserController(UserRepository userRepository) { this.userRepository = userRepository; } @GetMapping("/user/all") public List<User> allUsers() { return userRepository.findAll(); } }
Configurações no arquivo
application.properties spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/geek_db?createDatabaseIfNotExist=true&allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC spring.datasource.username=dbuser spring.datasource.password=dbpassword spring.jpa.show-sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
Supõe-se que o seu computador esteja executando um servidor MySQL em uma porta padrão. Se necessário, ajuste o URL do servidor na cadeia de conexão, bem como o nome de usuário e a senha. Também vale a pena prestar atenção no parâmetro
createDatabaseIfNotExist . Graças a ele, ao conectar, criaremos um banco de dados chamado
geek_db se não estiver no servidor.
Adicionar Liquibase
Certamente você notou que uma configuração do Hibernate está
ausente , a saber,
spring.jpa.hibernate.ddl-auto . Na maioria dos manuais para iniciantes, o valor de
atualização é indicado, devido ao qual o Hibernate criará e ajustará a estrutura da tabela no próprio servidor, com base nas classes de entidade presentes no projeto. Essa abordagem pode ser usada se o esquema de dados for muito simples ou se o projeto estiver em treinamento, mas com um esquema um pouco complicado, os problemas provavelmente começarão, apenas porque não podemos controlar o processo de geração de scripts DDL do Hibernate. Outro problema é que, com essa abordagem, não há maneira fácil de reverter as alterações feitas no Hibernate na estrutura do banco de dados.
É para resolver os problemas acima que usaremos o utilitário
Liquibase . Felizmente para nós, ela é perfeitamente capaz de se integrar aos aplicativos Spring Boot! Para começar a usá-lo, você deve executar as seguintes etapas
Inclua a configuração no arquivo
application.properties spring.jpa.hibernate.ddl-auto=none
Isso é para garantir que o Hibernate não execute nenhuma ação para modificar o circuito, como A Liquibase fará isso agora. Teoricamente, aqui também é possível usar o valor de
validação para controle adicional sobre a correção da estrutura da tabela.
Adicione uma dependência ao
pom.xml <dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> </dependency>
Após adicioná-lo, a inicialização do Spring criará automaticamente um bean especial chamado liquibase, que executará todas as ações para configurar o esquema do banco de dados com base nos scripts do Liquibase toda vez que o aplicativo for iniciado.
Agora você precisa adicionar o próprio script Liquibase, que criará a tabela que precisamos. Na pasta / src / main / resources / db / changelog, crie um arquivo chamado db.changelog-master.yaml e adicione o seguinte conteúdo a ele
databaseChangeLog: - logicalFilePath: db/changelog/db.changelog-lesson1.yaml - changeSet: id: 1 author: your_liquibase_username changes: - createTable: tableName: users columns: - column: name: id type: BIGINT autoIncrement: true constraints: primaryKey: true nullable: false - column: name: username type: varchar(50) constraints: unique: true nullable: false - column: name: password type: varchar(512) constraints: nullable: false - column: name: first_name type: varchar(50) - column: name: last_name type: varchar(50) - column: name: email type: varchar(50)
Vamos analisar o conteúdo desse script. Primeiro de tudo, ele contém um changeSet. ChangeSet é um análogo de uma confirmação em sistemas de controle de versão, como Git ou SVN. Por analogia com uma confirmação, as alterações feitas como parte de um changeSet podem ser revertidas ou revertidas no servidor de banco de dados. Cada changeSet deve ter um identificador exclusivo com o qual o Liquibase determina se um determinado changeSet foi bombeado para esse banco de dados ou não.
ChangeSet contém um comando para criar uma tabela, e a estrutura da tabela é descrita pelo Liquibase, e não um script SQL. Graças a isso, esse arquivo se torna multiplataforma. O Liquibase irá gerar um script SQL, dependendo do servidor de banco de dados usado. Além disso, se precisarmos reverter o changeSet fornecido, o Liquibase poderá criar automaticamente um script para excluir a tabela especificada. Se usamos scripts SQL, teríamos que escrever manualmente um script para reverter as alterações. Na seção de
travamentos , temos apenas uma equipe e isso é considerado uma boa prática, apesar do fato de que pode haver qualquer número de equipes em um
changeSet .
O código escrito é suficiente para executar o programa, mas para ver mais claramente os resultados de seu trabalho, vamos adicionar outra
changeSet , que preencherá a tabela com dados.
- changeSet: id: 2 author: your_liquibase_username comment: "Create admin user" changes: - insert: tableName: users columns: - column: name: username value: "admin" - column: name: password value: "admin" - column: name: email value: "admin@server.com" - insert: tableName: users columns: - column: name: username value: "guest" - column: name: password value: "guest" - column: name: email value: "guest@server.com" rollback: - delete: tableName: users where: username in ('admin', 'guest')
Nesse caso, já tivemos que escrever manualmente um bloco para operações de reversão, como O Liquibase não pode criar automaticamente SQL de reversão ao trabalhar com dados. Em geral, trabalhar com dados no banco de dados não está entre os principais recursos do Liquibase e é limitado apenas às operações mais simples de inserção, exclusão ou alteração. A propósito, se você precisar de mais, então aqui você pode usar as ferramentas da empresa
Red Gate .
Então, vamos executar nosso aplicativo e tentar seguir o link
http: // localhost: 8080 / user / all . Se o aplicativo for iniciado, você verá uma resposta JSON com informações sobre os dois usuários que foram adicionados à tabela. Também vale a pena dar uma olhada nos logs de inicialização do aplicativo, nos quais você pode ver os scripts que o Liquibase executa para inicializar o banco de dados. Atenção especial deve ser dada à tabela
DATABASECHANGELOG . É nele que o Liquibase armazena o log das alterações feitas no banco de dados.
Por enquanto é tudo. Depois de algum tempo, pretendo publicar uma continuação sobre o uso do
liquibase-maven-plugin para gerar scripts automaticamente comparando estruturas de banco de dados e
revertendo as alterações feitas.
Ficaria muito grato por quaisquer adições e comentários!
PS Código completo escrito com base neste artigo
github.com/usharik/spring-liquibase-demo/tree/part-1Continua em
habr.com/en/post/460907