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

标签 java spring mongodb spring-data

我正在使用 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 转换,有没有办法通过 Mongodriver API 提取 Collection.user.$username

我一直在寻找不成功。

最佳答案

不是真的,因为 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;
}

编辑

在检查 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 构建模板:

模板 = 新的 MongoTemplate (new MySimpleMongoDbFactory(new MongoClient(), "test"));

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

关于java - 从实际复制的 DuplicateKeyException 中检索特定的 MongoDB 键 (Java/Spring),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23094415/

相关文章:

java - 我正在尝试开发 Web 服务 REST 应用程序。我不知道如何解决以下错误

node.js - 我难以将 Node 与 MongoDB 连接的原因

java - For 循环返回时不退出

Java 8 从每个字段中删除字符串值,其中 "string"值来自自定义对象

java - Spring Boot war 部署无法在差异机器上使用相同的配置进行初始化

node.js - 资源暂时不可用。 key 身份验证失败(错误 -18)。 (错误#35)

java - 通过在一个集合中进行更改来反射(reflect)多个 mongodb 集合中的更改

java - 作为 Delphi 程序员理解 Java

java - 将 gson.JsonObject 转换为 JSONObject

java - 在Spring-WS中如何使用WebServiceMessageDrivenBean?