我正在使用 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/