sql >> Database >  >> NoSQL >> MongoDB

De specifieke MongoDB-sleutel ophalen van DuplicateKeyException die daadwerkelijk is gedupliceerd (Java/Spring)

Niet echt, aangezien de Mongo Java Driver de laatste fout al blootlegt als een geconstrueerde String:

writeResult.getLastError().get("err") geeft iets terug als:

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

Dit geldt ook voor de shell en elke bestuurder, denk ik.

Een redelijke oplossing, denk ik, is om dergelijke dubbele sleuteluitzondering te ontleden met behulp van een aangepaste uitzondering:

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

... een aangepaste uitzonderingsvertaler:

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

... en de veerconfiguratie correct instellen:

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

BEWERKEN

Na inspectie van MongoTemplate code (1.4.1.RELEASE), lijkt het erop dat er intern een SimpleMongoDbFactory wordt gebruikt om een ​​standaard MongoExceptionTranslator . op te halen , dus degene die is gemaakt met MongoFactoryBean wordt geschaduwd. Had dat deel gemist.

De oplossing is om SimpleMongoDbFactory te overschrijven (vergeet MongoFactoryBean , het is nutteloos in deze context):

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 kunt u een sjabloon maken met behulp van de aangepaste MongoDbFactory :

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

Had het geprobeerd, en deze werkt voor mij.



  1. Passport.js en Mongoose.js vullen Gebruiker bij inloggen - verliest ingevuld veld op req.user

  2. Wat moet ik gebruiken? Socket.io-kamers of Redis pub-sub?

  3. MongoDB op mlab-verificatie mislukt

  4. Spring RedisTemplate:serialiseer meerdere modelklassen in JSON. Wilt u meerdere RedisTemplates gebruiken?