从实际重复的 DuplicateKeyException 中检索特定的 MongoDB 键 (Java/Spring)

2024-01-02

我正在使用 Spring-Data/MongoDB,并在保存/插入时正确捕获重复的键。

举个例子,假设我有一个用户被保存到一个集合中。 User 对象用两个注释@Indexed(unique=true)(两个唯一的键)。假设它们是“电子邮件”和“用户名”。如何检索在插入过程中实际重复的索引。

我得到的最接近的是当我执行此类示例代码时:

public boolean createNewUser() {
    MongoTemplate operations = RepositoryFactory.getMongoOperationsInstance();
    try {
        log.debug("Saving new user to DB");
        operations.save(this);
        return true;
    } catch (DuplicateKeyException dke) {
        log.debug("User with same username or email found");    
        log.debug(operations.getDb().getLastError());
        return false;
    }
}

这会打印字符串:

{ "serverUsed" : "/127.0.0.1:27017" , "err" : "E11000 duplicate key error index: Collection.user.$username  dup key: { : \"user\" }" , "code" : 11000 , "n" : 0 , "connectionId" : 17 , "ok" : 1.0}

没有愚蠢的字符串操作或 Json 转换,有没有办法提取Collection.user.$username通过 Mongodriver API?

我一直在寻找没有成功。


事实并非如此,因为 Mongo Java 驱动程序已经将最后一个错误公开为构造的字符串:

writeResult.getLastError().get("err")返回诸如以下内容:

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

我想,对于 shell 和每个驱动程序来说也是如此。

我认为一个合理的解决方案是使用自定义异常来解析此类重复的键异常:

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

...自定义异常翻译器:

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

...并正确设置 Spring 配置:

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

EDIT

检查后MongoTemplate代码(1.4.1.RELEASE),似乎内部是SimpleMongoDbFactory用于检索默认值MongoExceptionTranslator,所以用创建的MongoFactoryBean被阴影覆盖。错过了那部分。

解决方案是覆盖SimpleMongoDbFactory(把...忘了吧MongoFactoryBean,在这种情况下没有用):

public class MySimpleMongoDbFactory extends SimpleMongoDbFactory {

    PersistenceExceptionTranslator translator = new       
            DetailedDuplicateKeyExceptionTransaltor();

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

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

现在您可以使用自定义构建模板MongoDbFactory:

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

已经尝试过了,这个对我有用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从实际重复的 DuplicateKeyException 中检索特定的 MongoDB 键 (Java/Spring) 的相关文章

随机推荐