sql >> Databasteknik >  >> NoSQL >> MongoDB

Hämta den specifika MongoDB-nyckeln från DuplicateKeyException som faktiskt duplicerades (Java/Spring)

Inte riktigt, eftersom Mongo Java Driver redan avslöjar det sista felet som en konstruerad sträng:

writeResult.getLastError().get("err") returnerar något som:

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

Detta gäller även för skalet och varje förare, föreställer jag mig.

En rimlig lösning, tycker jag, är att analysera ett sådant dubblettnyckelundantag med hjälp av ett anpassat undantag:

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

... en anpassad undantagsöversättare:

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);
    }
}

... och ställ in fjäderkonfigurationen korrekt:

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

REDIGERA

Efter att ha inspekterat MongoTemplate kod (1.4.1.RELEASE), verkar det som internt en SimpleMongoDbFactory används för att hämta en standard MongoExceptionTranslator , alltså den som skapades med MongoFactoryBean är skuggad. Hade missat den delen.

Lösningen är att åsidosätta SimpleMongoDbFactory (glöm MongoFactoryBean , det är värdelöst i det här sammanhanget):

public class MySimpleMongoDbFactory extends SimpleMongoDbFactory {

    PersistenceExceptionTranslator translator = new       
            DetailedDuplicateKeyExceptionTransaltor();

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

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

Nu kan du konstruera en mall med den anpassade MongoDbFactory :

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

Hade provat, och den här fungerar för mig.



  1. Slaget om NoSQL-databaserna - Jämför MongoDB och CouchDB

  2. Är MongoDB ChangeStream ResumeToken unik globalt?

  3. Sortering efter relevans med MongoDB

  4. Hur ser man vilka frågor som använder ett index i MongoDB?