DDD ID Generierung

Nachdem das Problem klar ist kann ich mir folgende Lösungswege vorstellen:
-Twitter Snowflake Methode - wenn du dirs selber zusamenbaust kannst du es ja an deine Anforderungen anpassen.
-IDGeneratoren reservieren sich ihre eigenen ID-Intervalle bei einer zentralen Instanz (der DB) - könnten sich wieder ganz neue Probleme ergeben, ausserdem die IDs nicht mehr schön nach Erstelldatum sortiert
-Beim hinzufügen eines neuen Knotens müssen alle anderen Knoten alles persistieren bzw. sich abstimmen - zulasten der Skalierbarkeit, das wird sicher immer aufwändiger, je mehr Knoten

Ich glaube egal welchen Weg man hier geht (gibt sicher noch andere Möglichkeiten) man hat immer irgendeinen Tradeoff.

Das sehe ich auch so. Nur bei einem Einzelknoten sehe ich die Sache ziemlich eindeutig: da werde ich wahrscheinlich einen ganz einfachen IdGenerator verwenden, wie ich ihn in #27 schon gepostet habe, allerdings für 64bit-IDs, die ich dann auch Datenbankweit verwenden werde.
Das eliminiert auch die Problematik mit dem equals bei tieferen Vererbungshierarchien, weil auch bei unterschiedlichen Klassen keine IDs doppelt vorkommen können. Bei der Initialisierung ist die Ermittlung der höchsten ID allerdings etwas komplizierter (allerdings nur für den Fall, dass der Knoten nicht kontrolliert heruntergefahren wurde).
Bei mehreren Knoten gibt es bei 64bittigen IDs einige Möglichkeiten, wie sich im Verlauf des Threads herausgestellt hat.
Und das Design erscheint mir auch flexibel genug, diese Variationen umzusetzen.

Dennoch: wenn jemand bzgl. des Designs noch Vorschläge hat, bin ich offen dafür.

Mittlerweile habe ich @nillehammer s Vorschlag aus #15 umgesetzt und die @Version-Annotation verwendet, um zu prüfen, ob die Entity bereits persistiert ist.
Wie in #15 auch geschrieben, spare ich mir dadurch einen Listener. Den @PrePersist-Listener kann ich ggf. auch noch rauswerfen, weil dieser Zustand eigentlich nicht eintreten sollte. Kritisch sind da noch Punkte wie die Objekterzeugung mittels Jackson, weshalb ich den Listener erst einmal drin gelassen habe. (Edit: andererseits fliegt aber sofort eine Exception, sobald die Entity in die Datenbank geschrieben werden soll, weil der PK nicht null sein darf.)
Das ganze sieht mittlerweile so aus (ich verwende Datenbankweite IDs, weshalb in equals() kein Check auf die genaue Klasse gemacht werden muss):

import org.springframework.data.domain.Persistable;

import javax.annotation.Nonnull;
import javax.persistence.*;
import java.io.Serializable;

import static com.google.common.base.Preconditions.checkNotNull;

@MappedSuperclass
public abstract class AbstractEarlyIdPersistable<ID extends Serializable> implements Persistable<ID> {
    private static final long serialVersionUID = 36158918737965860L;
    @Id
    private ID id;
    @Version
    @Column(nullable = false, name = "opt_lock_version")
    private Integer version;

    protected AbstractEarlyIdPersistable() {
    }

    protected AbstractEarlyIdPersistable(@Nonnull ID id) {
        this.id = checkNotNull(id);
    }

    @Override
    public ID getId() {
        return id;
    }

    @Override
    public boolean isNew() {
        return version == null;
    }

    @PrePersist
    private void checkId() {
        if (id == null)
            throw new IllegalStateException(String.format("Entity of class %s should get persistet but has no id set.",
                    this.getClass().getCanonicalName()));
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof AbstractEarlyIdPersistable)) return false;

        AbstractEarlyIdPersistable that = (AbstractEarlyIdPersistable) o;

        return id.equals(that.id);
    }

    @Override
    public int hashCode() {
        return id.hashCode();
    }
}