Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Automatische Schlüsselgenerierung mit MySQL und Oracle in den Ruhezustand versetzen

Auch wenn Sie GenerationType.AUTO verwendet haben Ohne einen SEQUENCE-spezifischen Parameter könnten Sie die zugewiesenen Bezeichner nicht speichern.

Es gibt einige Problemumgehungen, wenn Sie bereit sind, einige Kompromisse einzugehen:

  1. Eine Möglichkeit wäre, auf die zugewiesenen Identifier umzuschalten. Sie können UUID-Bezeichner verwenden, die sowohl für MySQL als auch für Oracle funktionieren, und Sie können die Werte auch manuell zuweisen.

  2. Eine andere Möglichkeit ist die Verwendung eines benutzerdefinierten Tabellengenerators.

Zuerst definieren Sie eine identifizierbare Schnittstelle:

    public interface Identifiable<T extends Serializable> {
        T getId();
    }

Dann erweitern Sie den Tabellengenerator:

    public class AssignedTableGenerator extends TableGenerator {

        @Override
        public Serializable generate(SessionImplementor session, Object obj) {
            if(obj instanceof Identifiable) {
                Identifiable identifiable = (Identifiable) obj;
                Serializable id = identifiable.getId();
                if(id != null) {
                    return id;
                }
            }
            return super.generate(session, obj);
        }
    }

Dieser Generator ist in der Lage, zugewiesene Identifikatoren mit synthetisch generierten zu mischen:

    doInTransaction(session -> {
        for (int i = 0; i < 5; i++) {
            session.persist(new AssignTableSequenceIdentifier());
        }
        AssignTableSequenceIdentifier tableSequenceIdentifier = new AssignTableSequenceIdentifier();
        tableSequenceIdentifier.id = -1L;
        session.merge(tableSequenceIdentifier);
        session.flush();
    });

Generieren der folgenden Anweisungen:

    select tbl.next_val from sequence_table tbl where tbl.sequence_name=default for update
    insert into sequence_table (sequence_name, next_val)  values (default,1)
    update sequence_table set next_val=2  where next_val=1 and sequence_name=default
    select tbl.next_val from sequence_table tbl where tbl.sequence_name=default for update
    update sequence_table set next_val=3  where next_val=2 and sequence_name=default
    select tbl.next_val from sequence_table tbl where tbl.sequence_name=default for update
    update sequence_table set next_val=4  where next_val=3 and sequence_name=default
    select tbl.next_val from sequence_table tbl where tbl.sequence_name=default for update
    update sequence_table set next_val=5  where next_val=4 and sequence_name=default
    select tbl.next_val from sequence_table tbl where tbl.sequence_name=default for update
    update sequence_table set next_val=6  where next_val=5 and sequence_name=default
    select identityvs0_.id as id1_0_0_ from assigneTableIdentifier identityvs0_ where identityvs0_.id=-1
    insert into assigneTableIdentifier (id) values (1, 2)
    insert into assigneTableIdentifier (id) values (2, 4)
    insert into assigneTableIdentifier (id) values (5, -1)

Für Oracle können Sie die SEQUENCE und die zugeordneten Generatoren kombinieren. Kurz gesagt, unter Berücksichtigung des folgenden Generators:

public class AssignedSequenceStyleGenerator 
    extends SequenceStyleGenerator {
 
    @Override
    public Serializable generate(SessionImplementor session, 
        Object obj) {
        if(obj instanceof Identifiable) {
            Identifiable identifiable = (Identifiable) obj;
            Serializable id = identifiable.getId();
            if(id != null) {
                return id;
            }
        }
        return super.generate(session, obj);
    }
}

Sie können es Ihren Entitäten wie folgt zuordnen:

@Id
@GenericGenerator(
    name = "assigned-sequence",
    strategy = "com.vladmihalcea.book.hpjp.hibernate.identifier.AssignedSequenceStyleGenerator",
    parameters = @org.hibernate.annotations.Parameter(
        name = "sequence_name", 
        value = "post_sequence"
    )
)
@GeneratedValue(
    generator = "assigned-sequence", 
    strategy = GenerationType.SEQUENCE
)
private Long id;

Der gesamte Code ist auf GitHub verfügbar und funktioniert wie am Schnürchen.