Spring Data (liquibase)

Introduction

This page show simple Spring Data JPA repositories and Entities for accessing Liquibase tables:

Entities

package edu.cou.myapp.entity.liquibase;


import java.util.Date;


import javax.persistence.Column;

import javax.persistence.EmbeddedId;

import javax.persistence.Entity;

import javax.persistence.Table;

import javax.persistence.Temporal;

import javax.persistence.TemporalType;


import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;


/**

 * https://www.liquibase.org/documentation/databasechangelog_table.html<br>

 * <br>

 * There is no primary key on the table. This is to avoid any database-specific restrictions on key lengths. The composite of “id”, “author”, and “filename” is unique across all rows of the table.<br>

 */

@NoArgsConstructor

@AllArgsConstructor

@Data

@Entity

@Table(name = "DATABASECHANGELOG")

public class DatabaseChangelog {


  /**

   * Identifier.

   */

  @EmbeddedId

  private DatabaseChangelogId id;


  @Column(name = "DATEEXECUTED")

  @Temporal(TemporalType.TIMESTAMP)

  private Date dateExecuted;


  @Column(name = "ORDEREXECUTED")

  private Integer orderExecuted;


  @Column(name = "EXECTYPE")

  private String execType;


  @Column(name = "MD5SUM")

  private String md5Sum;


  @Column(name = "DESCRIPTION")

  private String description;


  @Column(name = "COMMENTS")

  private String comments;


  @Column(name = "TAG")

  private String tag;


  @Column(name = "LIQUIBASE")

  private String liquibase;


  @Column(name = "CONTEXTS")

  private String contexts;


  @Column(name = "LABELS")

  private String labels;


  @Column(name = "DEPLOYMENT_ID")

  private String deploymentId;


}



package edu.cou.myapp.entity.liquibase;


import java.io.Serializable;


import javax.persistence.Column;

import javax.persistence.Embeddable;


import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.EqualsAndHashCode;

import lombok.NoArgsConstructor;


/**

 * Entity id & DTO.<br>

 */

@Data

@NoArgsConstructor

@AllArgsConstructor

@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true)

@Embeddable

public class DatabaseChangelogId implements Serializable {


  /**

   * 

   */

  private static final long serialVersionUID = -3341096236731313707L;


  @EqualsAndHashCode.Include

  @Column(name = "ID")

  private String id;


  @EqualsAndHashCode.Include

  @Column(name = "AUTHOR")

  private String author;


  @EqualsAndHashCode.Include

  @Column(name = "FILENAME")

  private String filename;


}



package edu.cou.myapp.entity.liquibase;


import java.util.Date;


import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.Id;

import javax.persistence.Table;

import javax.persistence.Temporal;

import javax.persistence.TemporalType;


import lombok.Getter;

import lombok.NoArgsConstructor;


/**

 * It represents a record in Liquibase table DATABASECHANGELOGLOCK<br>

 * https://www.liquibase.org/documentation/databasechangeloglock_table.html <br>

 * 

 * JPA entity that represents a 'Liquibase lock'.<br>

 */

@Getter

@Entity

@NoArgsConstructor

@Table(name = "DATABASECHANGELOGLOCK")

public class DatabaseChangelogLock {


  /** ID of the lock. There is currently only one lock. */

  @Id

  @Column(name = "ID")

  private Integer id;


  /**

   * Set to "1" if Liquibase is running against this database. Otherwise set to "0".

   */

  @Column(name = "LOCKED", nullable = false, updatable = true)

  private Integer locked; // NOSONAR


  /**

   * Date and time that the lock was granted.<br>

   * DATETIME

   */

  @Column(name = "LOCKGRANTED", nullable = true, updatable = true)

  @Temporal(TemporalType.TIMESTAMP)

  private Date lockGranted; // Maybe better: java.time.Instant


  /**

   * Human-readable description of who the lock was granted to.<br>

   * VARCHAR(255)

   */

  @Column(name = "LOCKEDBY", nullable = true, updatable = true)

  private String lockedBy; // NOSONAR

}



Repositories

Release the liquibase lock:

package edu.cou.myapp.repository.liquibase;


import org.springframework.data.jpa.repository.JpaRepository;

import org.springframework.data.jpa.repository.Query;


import edu.cou.myapp.entity.liquibase.DatabaseChangelogLock;


/**

 * Liquibase table "DATABASECHANGELOGLOCK".<br>

 * https://www.liquibase.org/documentation/databasechangeloglock_table.html <br>

 * <br>

 * If Liquibase gets locked, log will show:<br>

 * SELECT LOCKED FROM public.databasechangeloglock WHERE ID=1<br>

 * <br>

 * (+)It can be unlocked with:<br>

 * UPDATE DATABASECHANGELOGLOCK SET LOCKED=FALSE, LOCKGRANTED=null, LOCKEDBY=null where ID=1;<br>

 * <br>

 * (+)Alternatively using Spring Data REST:<br>

 * https://sites.google.com/site/pawneecity/sprint-boot/data-rest-spring-boot<br>

 * <br>

 */

public interface DatabaseChangelogLockRepository extends

    JpaRepository<DatabaseChangelogLock, Integer> {


  /**

   * Release the liquibase lock.<br>

   * WARNING: ONLY if it's locked unexpectedly

   */

  @Query(

      value = "UPDATE DATABASECHANGELOGLOCK SET LOCKED=false, LOCKGRANTED=null, LOCKEDBY=null WHERE ID=1",

      nativeQuery = true)

  void releaseLiquibaseLock();


}



package edu.cou.myapp.repository.liquibase;


import org.springframework.data.jpa.repository.JpaRepository;


import edu.cou.myapp.entity.liquibase.DatabaseChangelog;

import edu.cou.myapp.entity.liquibase.DatabaseChangelogId;


/**

 * Liquibase table "DATABASECHANGELOG".<br>

 * https://www.liquibase.org/documentation/databasechangelog_table.html<br>

 */

public interface DatabaseChangelogRepository extends

    JpaRepository<DatabaseChangelog, DatabaseChangelogId> {


}