Konventionen achten mit SpringPhysicalNamingStrategy

“Alles was ich habe ist ein Name und den habe ich von einem anderen.”

Heinrich Dove

Wer als Java Entwickler mit Datenbank Experten zusammenarbeiten darf, kennt deren Hinwendung zu großgeschrieben Bezeichnern. Da heißen die Tabellen dann ANCESTOR_TREE und die Attribute NAME, DESCRIPTION, CREATED_BY.

Diese Namenskonvention gilt in Java aber nur für die Namen von Konstanten, weder für die Namen von Klassen noch ihrer Instanz-Attribute. Eine Java konforme Entity Klasse AncestorTree sieht wie folgt aus.

@Entity
@Data
public class AncestorTree {
  @Id
  private Long id;
  private String name;
  private String description;
  @CreatedBy
  private String createdBy;
}

Spring Data JPA produziert, basierend auf dieser Klasse, eine Tabelle mit dem Namen ancestor_tree und Spalten mit den Namen name, description und created_by.

Damit die Namen den Wünschen der Datenbank Experten entsprechen, können Annotationen verwendet werden. Mit @Table kann der Name der Datenbanktabelle und mit @Column der Name der Tabellenspalte spezifiziert werden.

@Entity
@Data
@Table(name = "ANCESTOR_TREE")
public class AncestorTree {
  @Id
  @Column(name = "ID")
  private Long id;
  @Column(name = "NAME")
  private String name;
  @Column(name = "DESCRIPTION")
  private String description;
  @CreatedBy
  @Column(name = "CREATED_BY")
  private String createdBy;
}

Diese Lösung ist aber insofern unschön, weil jedes Attribut mit einer Annotation versehen werden musste. Die gesamte Klasse wird regelrecht mit Annotationen verschmutzt, die keinen wirklichen Mehrwert besitzen.

Eine andere Lösung bietet sich über die PhysicalNamingStrategy von Hibernate an. Von Implementierungen dieses Interfaces werden die tatsächlichen Namen erzeugt, die für Klassen und Attribute in der Datenbank verwendet werden. Spring Data JPA liefert eine eigene Implementierung mit, die in die Camel-Case Schreibweise von Java passend Unterstriche einfügt und dann alles in Kleinbuchstaben umwandelt. Dies entspricht schon fast dem gewünschten Ergebnis, nur werden Großbuchstaben benötigt.

Eine eigene PhysicalNamingStrategy überschreibt, daher in der SpringPhysicalNamingStrategy die entsprechende Methode und nutzt statt der Methode toLowerCase die Methode toUpperCase.

public class UpperCaseNamingStrategy extends SpringPhysicalNamingStrategy {
  @Override
  protected Identifier getIdentifier(String name, boolean quoted, JdbcEnvironment jdbcEnvironment) {
    if (isCaseInsensitive(jdbcEnvironment)) {
      name= name.toUpperCase(Locale.ROOT);
    }
    return new Identifier(name, quoted);
  }
}

Damit die UpperCaseNamingStrategy auch verwendet wird, muss sie noch in der application.properties Konfigurationsdatei bekanntgemacht werden.

spring.jpa.hibernate.naming.physical-strategy=de.schegge.persistence.UppercaseNamingStrategy

Nun werden alle verwendeten Namen in der gewünschten Upper-Case Konvention für die Datenbank generiert. Die Datenbank Experten freuen sich und die Java Entwickler freuen sich auch.