Freelance Software Consultant

  • Twitter
  • Google Plus

kontakt@cqueiser.de

  • Home
  • Über mich
  • Artikel
  • Kontakt

SchemaManagementException

Posted:
18.02.2020

Tags:
Exception, H2, Hibernate, Java, SpringBoot

Comments: 0

Sobald man in seinem Projekt mit einer Datenbank zu tun hat, ist es ratsam die Datenbank-Tabellen mittels ORM (object-relational mapping) in objektorientierten Entitäten abzubilden.

Im Symfony (PHP) ist Doctrine die erste Wahl, in Spring Boot (Java) ist es Hibernate.

Damit das Validieren des Datenbank-Schemas möglich ist, benötigt man eine Datenbank worin die Migrations-Scripte geladen und ausgeführt werden können.

Es möglich eine Datenbank mittels Docker zu starten oder man wählt stattdessen eine In-Memory-Datenbank wie H2. Der Vorteil bei der In-Memory-Datenbank ist es, dass sie sehr schnell geladen wird, da alles im Arbeitsspeicher ausgeführt wird.

Letztens ist ein interessantes Problem aufgefallen. Die Validierung des Datenbank-Schemas wurde erst nachträglich aktiviert und beim ausführen der Acceptance-Tests, wo die Datenbank geladen wird und auch alle Migrations-Scripte ausgeführt werden, ist es zu einer Exception gekommen. Die Exception lautet SchemaManagementException – Schema-validation: wrong column type encountered in column [bar] in table [foo]; found [double (Types#DOUBLE)], but expecting [float (Types#FLOAT)].

Setup

Die Schema-Validierung wird für das Test-Environment in der application-test.yml aktiviert:

// application-test.yaml
database:
  username: sa
  password: sa
  host: jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring:
  jpa.hibernate.ddl-auto: validate

Das Datenbank-Migrations-Script:

// V1__create_table_foo.sql
CREATE Table Foo (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `bar` float DEFAULT NULL,
  PRIMARY KEY (`id`)
);

Die dazugehörige Entität:

// Foo.java
import lombok.Data;
import javax.persistence.*;

@Data
@Entity
@Table
public class Foo {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @Column
  private Float bar;
}

Problem

Float ist in H2 nicht vorhanden. Der Fallback dafür ist der Datentyp Double. Sobald Hibernate die Entitäten mit den Datenbanktabellen validiert kommt es zu einer Fehlermeldung, dass die Datentypen nicht identisch sind, da H2 den Datentyp von Float selbstständig zu Double geändert hat.

Der Unterschied zwischen den Datentypen Float und Double is der, dass Float 32 Bit lang ist und Double 64 Bit. Das heißt, dass Double eine höhere Genauigkeit aufweist.

Sofern in dem Feld Währungseinheiten gespeichert werden sollen, wird der Java Datentyp BigDecimal und für MySQL äquivalent der Datentyp DECIMAL(20,2) empfohlen.

Lösung

Die Lösung lautet, dass das Attribut in der Entität den Fallback direkt zugewiesen bekommt, in diesem Fall also Double. Also ändern wir das Attribut der Entität auf Double.

// Foo.java
import lombok.Data;

import javax.persistence.*;

@Data
@Entity
@Table
public class Foo {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @Column
   private Double bar;
}

Zusätzlich muss auch in der Datenbank der Datentyp der Spalte bar auf Double geändert werden. Entweder initial richtig mit solch einem Migrationsscript:

// V1__create_table_foo_double.sql
CREATE Table Foo (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `bar` double DEFAULT NULL,
  PRIMARY KEY (`id`)
);

Sofern die Migration mit dem fehlerhaften Datentyp bereits ohne Validierung bis ins Live Environment ausgeführt wurde, dann muss per zusätzlichem Migrations-Script der Datentyp nachträglich geändert werden:

// V2__modify_datatype_to_double.sql
ALTER TABLE `foo` MODIFY `bar` double;

Nun sind in der produktiven MySQL Datenbank, in der H2 Datenbank für die Acceptance Tests und in der Java Entität alle Datentypen identisch.

Doch Vorsicht: Änderungen an der Datenbank können nicht widerrufen werden. Deshalb ist es ratsam ein Backup von der Datenbank zu erstellen.


  • Exception
  • H2
  • Hibernate
  • Java
  • SpringBoot

Share This Post

  • Facebook
  • Twitter
  • Google Plus

About

cqueiser

Christopher Queiser – Freiberuflicher Software-Developer. Spezialisiert in PHP / Symfony in Version 3 und 4 & Wordpress. Seine letzte Herausforderung war ein Master of Science in "IT-Management" FOM.

Related Posts

Leave A Comment

Click here to cancel reply.

Name*

Mail*

Website

Recent Posts

  • SchemaManagementException
  • Das Runde muss ins Eckige
  • MySQL Date NOT NULL DEFAULT ‘0000-00-00’
  • PHP var_dump(0123)
  • PageSpeed

Archives

  • February 2020
  • December 2018
  • August 2017
  • March 2017
  • October 2013

Categories

  • Uncategorized
  • Home
  • Kontakt
  • Impressum
  • Datenschutzerklärung

Blücherstrasse 22, 10961 Berlin, Deutschland

E-mail: kontakt@cqueiser.de

Soziale Präsenz


  • Twitter
  • Google Plus

Copyright © 2016 cqueiser.de

We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it.OkRead more