Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como criar uma classe de modelo de entidade genérica que suporta id genérico, incluindo ids gerados automaticamente?


Não tentei isso, mas de acordo com a API do Hibernate, isso não deve ser complicado criando uma implementação personalizada de IdentityGenerator .

É o método generate e o objeto para o qual você está gerando o valor para que você possa verificar o tipo do campo id e retornar o valor apropriado para sua chave primária.
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;

            }

        }
    }

Tendo isso simplesmente use-o como sua estratégia de geração:
@MappedSuperclass
public abstract class BaseEntity<T> implements Serializable {
    @Id
    @GenericGenerator(name="seq_id", strategy="my.package.DynamicGenerator")
    protected T id;
}

Para o Hibernate 4, você deve implementar IdentifierGenerator interface.

Como acima é aceito para o Hibernate, ainda deve ser possível criá-lo de maneira mais genérica para qualquer provedor "compatível com jpa". De acordo com a API JPA em GeneratedValue anotação, você pode fornecer seu gerador personalizado. Isso significa que você pode fornecer o nome do seu gerador personalizado e deve implementar esse gerador para cada provedor jpa.

Isso significaria que você precisa anotar BaseEntity com a seguinte anotação
@MappedSuperclass
public abstract class BaseEntity<T> implements Serializable {
    @Id
    @GeneratedValue(generator="my-custom-generator")
    protected T id;
}

Agora você precisa registrar o gerador personalizado com o nome "my-custom-generator" para cada provedor jpa que você gostaria de usar.

Para o Hibernate, isso é feito grosseiramente pela anotação @GenericGenerator como mostrado antes (adicionando @GenericGenerator(name="my-custom-generator", strategy="my.package.DynamicGenerator" para BaseEntity classe em qualquer id campo ou BaseEntity nível de classe deve ser suficiente).

No EclipseLink, vejo que você pode fazer isso via GeneratedValue anotação e registrá-la via 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);
    }

}    

Cada provedor deve fornecer uma maneira de registrar o gerador de id, portanto, você precisaria implementar e registrar uma estratégia de geração personalizada para cada um dos provedores se desejar oferecer suporte a todos eles.