sql >> Database >  >> RDS >> Mysql

Hoe maak je een generieke entiteitsmodelklasse die generieke id ondersteunt, inclusief automatisch gegenereerde id's?

Ik heb dit niet geprobeerd, maar volgens de api van Hibernate zou dit niet gecompliceerd moeten zijn door een aangepaste implementatie van IdentityGenerator .

De genereermethode krijgt en object waarvoor u de waarde genereert, zodat u het type id-veld kunt controleren en de juiste waarde voor uw primaire sleutel kunt retourneren.

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;

            }

        }
    }

Als je dit hebt, gebruik het dan gewoon als je generatiestrategie:

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

Voor Hibernate 4 moet u IdentifierGenerator interface.

Zoals hierboven is geaccepteerd voor Hibernate, zou het nog steeds mogelijk moeten zijn om het op een meer generieke manier te maken voor elke "jpa-compatibele" provider. Volgens JPA api in GeneratedValue annotatie kunt u uw aangepaste generator verstrekken. Dit betekent dat u de naam van uw aangepaste generator kunt opgeven en dat u deze generator voor elke jpa-provider moet implementeren.

Dit zou betekenen dat u BaseEntity moet annoteren met de volgende annotatie

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

Nu moet u een aangepaste generator registreren met de naam "my-custom-generator" voor elke jpa-provider die u wilt gebruiken.

Voor Hibernate wordt dit nors gedaan door @GenericGenerator-annotatie zoals eerder getoond (toevoegen van @GenericGenerator(name="my-custom-generator", strategy="my.package.DynamicGenerator" naar BaseEntity klasse op een van beide id veld of BaseEntity klasniveau zou voldoende moeten zijn).

In EclipseLink zie ik dat je dit kunt doen via GeneratedValue annotatie en het registreren 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);
    }

}    

Elke provider moet een manier bieden om id-generator te registreren, dus u moet een aangepaste generatiestrategie voor elke provider implementeren en registreren als u ze allemaal wilt ondersteunen.



  1. Waarde van primaire sleutel bijwerken met entiteitsraamwerk

  2. gebruik dezelfde trigger voor verschillende tabellen

  3. SQL Server 2008 Verticale gegevens naar Horizontaal

  4. Wat zijn benoemde pijpen?