Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wie erstelle ich eine generische Entitätsmodellklasse, die generische IDs einschließlich automatisch generierter IDs unterstützt?

Ich habe das nicht versucht, aber laut Hibernates API sollte dies nicht kompliziert sein, indem eine benutzerdefinierte Implementierung von IdentityGenerator .

Es generiert Methodengets und Objekte, für die Sie den Wert generieren, sodass Sie den Typ des ID-Felds überprüfen und den entsprechenden Wert für Ihren Primärschlüssel zurückgeben können.

public class DynamicGenerator  implements IdentityGenerator

        public Serializable generate(SessionImplementor session, Object object)
                throws HibernateException {

             if (shouldUseAutoincrementStartegy(object)) { // basing on object detect if this should be autoincrement or not, for example inspect the type of id field by using reflection - if the type is Integer use IdentityGenerator, otherwise another generator 
                 return new IdentityGenerator().generate(seession, object)
             } else { // else if (shouldUseTextKey)

                 String textKey = generateKey(session, object); // generate key for your object

                 // you can of course connect to database here and execute statements if you need:
                 // Connection connection = session.connection();
                 //  PreparedStatement ps = connection.prepareStatement("SELECT nextkey from text_keys_table");
                 // (...)

                 return textKey;

            }

        }
    }

Wenn Sie dies haben, verwenden Sie es einfach als Ihre Generierungsstrategie:

@MappedSuperclass
public abstract class BaseEntity<T> implements Serializable {
    @Id
    @GenericGenerator(name="seq_id", strategy="my.package.DynamicGenerator")
    protected T id;
}

Für Hibernate 4 sollten Sie IdentifierGenerator Schnittstelle.

Da oben für Hibernate akzeptiert wird, sollte es immer noch möglich sein, es für jeden "jpa-kompatiblen" Anbieter auf allgemeinere Weise zu erstellen. Laut JPA-API in GeneratedValue Anmerkung können Sie Ihren benutzerdefinierten Generator bereitstellen. Das bedeutet, dass Sie den Namen Ihres benutzerdefinierten Generators angeben können und diesen Generator für jeden jpa-Anbieter implementieren sollten.

Dies würde bedeuten, dass Sie BaseEntity mit der folgenden Anmerkung annotieren müssen

@MappedSuperclass
public abstract class BaseEntity<T> implements Serializable {
    @Id
    @GeneratedValue(generator="my-custom-generator")
    protected T id;
}

Jetzt müssen Sie den benutzerdefinierten Generator mit dem Namen "my-custom-generator" für jeden jpa-Anbieter registrieren, den Sie verwenden möchten.

Für Hibernate wird dies wie zuvor gezeigt durch die Annotation @GenericGenerator durchgeführt (Hinzufügen von @GenericGenerator(name="my-custom-generator", Strategy="my.package.DynamicGenerator"). zu BaseEntity Klasse entweder auf id Feld oder BaseEntity Klassenstufe sollte ausreichen).

In EclipseLink sehe ich, dass Sie dies über GeneratedValue Anmerkung und Registrierung über SessionCustomizer:

            properties.put(PersistenceUnitProperties.SESSION_CUSTOMIZER,
                    "my.custom.CustomIdGenerator");

public class CustomIdGenerator extends Sequence implements SessionCustomizer {


    @Override
    public Object getGeneratedValue(Accessor accessor,
            AbstractSession writeSession, String seqName) {
        return  "Id"; // generate the id
    }

    @Override
    public Vector getGeneratedVector(Accessor accessor,
            AbstractSession writeSession, String seqName, int size) {
        return null;
    }

    @Override
    protected void onConnect() {
    }

    @Override
    protected void onDisconnect() {
    }

    @Override
    public boolean shouldAcquireValueAfterInsert() {
        return false;
    }

    @Override
    public boolean shouldOverrideExistingValue(String seqName,
            Object existingValue) {
        return ((String) existingValue).isEmpty();
    }

    @Override
    public boolean shouldUseTransaction() {
        return false;
    }

    @Override
    public boolean shouldUsePreallocation() {
        return false;
    }

    public void customize(Session session) throws Exception {
        CustomIdGenerator sequence = new CustomIdGenerator ("my-custom-generator");

        session.getLogin().addSequence(sequence);
    }

}    

Jeder Anbieter muss eine Möglichkeit bieten, den ID-Generator zu registrieren, daher müssten Sie für jeden Anbieter eine benutzerdefinierte Generierungsstrategie implementieren und registrieren, wenn Sie alle unterstützen möchten.