Mysql
 sql >> Database >  >> RDS >> Mysql

Come creare una classe di modello di entità generica che supporti l'ID generico inclusi gli ID generati automaticamente?

Non l'ho provato, ma secondo l'API di Hibernate ciò non dovrebbe essere complicato creando un'implementazione personalizzata di Generatore di identità .

È il metodo di generazione ottiene e l'oggetto per il quale stai generando il valore in modo da poter controllare il tipo del campo id e restituire il valore appropriato per la tua chiave primaria.

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;

            }

        }
    }

Avendo questo, usalo semplicemente come strategia di generazione:

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

Per Hibernate 4, dovresti implementare IdentifierGenerator interfaccia.

Poiché sopra è accettato per Hibernate, dovrebbe essere ancora possibile crearlo in modo più generico per qualsiasi provider "compatibile con jpa". Secondo JPA API in GeneratedValue annotazione puoi fornire il tuo generatore personalizzato. Ciò significa che puoi fornire il nome del tuo generatore personalizzato e dovresti implementare questo generatore per ogni provider jpa.

Ciò significherebbe che devi annotare BaseEntity con la seguente annotazione

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

Ora devi registrare il generatore personalizzato con il nome "my-custom-generator" per ogni provider jpa che desideri utilizzare.

Per Hibernate questo è sicuramente fatto dall'annotazione @GenericGenerator come mostrato prima (aggiungendo @GenericGenerator(name="my-custom-generator", strategy="my.package.DynamicGenerator" a BaseEntity classe su id campo o BaseEntity il livello di classe dovrebbe essere sufficiente).

In EclipseLink vedo che puoi farlo tramite GeneratedValue annotazione e registrazione tramite 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);
    }

}    

Ogni provider deve fornire un modo per registrare il generatore di ID, quindi è necessario implementare e registrare una strategia di generazione personalizzata per ciascuno dei provider se si desidera supportarli tutti.