MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Recupero della chiave MongoDB specifica da DuplicateKeyException che è stata effettivamente duplicata (Java/Spring)

Non proprio, poiché il driver Mongo Java espone già l'ultimo errore come una stringa costruita:

writeResult.getLastError().get("err") restituisce qualcosa come:

insertDocument :: caused by :: 11000 E11000 duplicate key error index: test.person.$username dup key: { : "joe" }

Questo vale anche per la shell e tutti i driver, immagino.

Una soluzione ragionevole, penso, è analizzare tale eccezione di chiave duplicata utilizzando un'eccezione personalizzata:

public class DetailedDuplicateKeyException extends DuplicateKeyException {
    public DetailedDuplicateKeyException(String msg) {
        // Instead of just calling super parse the message here.
        super(msg);
    }
}

... un traduttore di eccezioni personalizzato:

public class DetailedDuplicateKeyExceptionTransaltor extends MongoExceptionTranslator {

    @Override
    public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
        if (ex instanceof MongoException.DuplicateKey) {
            return new DetailedDuplicateKeyException(ex.getMessage());
        }
        return super.translateExceptionIfPossible(ex);
    }
}

... e impostando correttamente la configurazione Spring:

@Bean
public MongoFactoryBean mongo() {
    MongoFactoryBean mongo = new MongoFactoryBean();
    mongo.setExceptionTranslator(new DetailedDuplicateKeyExceptionTransaltor());
    mongo.setHost("localhost");
    return mongo;
}

MODIFICA

Dopo aver controllato MongoTemplate codice (1.4.1.RELEASE), sembra che internamente una SimpleMongoDbFactory viene utilizzato per recuperare un MongoExceptionTranslator predefinito , quindi quello creato con MongoFactoryBean è in ombra. Avevo perso quella parte.

La soluzione è sovrascrivere SimpleMongoDbFactory (dimentica MongoFactoryBean , è inutile in questo contesto):

public class MySimpleMongoDbFactory extends SimpleMongoDbFactory {

    PersistenceExceptionTranslator translator = new       
            DetailedDuplicateKeyExceptionTransaltor();

    public MySimpleMongoDbFactory(Mongo mongo, String databaseName) {
        super(mongo, databaseName);
    }

    @Override
    public PersistenceExceptionTranslator getExceptionTranslator() {
        return translator;
    }
}

Ora puoi costruire un modello usando il MongoDbFactory personalizzato :

template = new MongoTemplate (new MySimpleMongoDbFactory(new MongoClient(), "test"));

Ci avevo provato e questo funziona per me.