事实并非如此,因为 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"));
已经尝试过了,这个对我有用。