Spring MongoDB - Почему уникальный индекс также применяется к встроенному документу?
У меня есть документ A с уникальным индексом и другой документ B, в который встроен A. Когда я пытаюсь сохранить 2 документа B с одним и тем же документом A, я получаю ошибку ключа дублирования. Зачем? Разве уникальный индекс не должен быть обеспечен только в той коллекции, где он указан?
A.java
@Document(collection = "docsA")
public class A {
@Id
private String id;
@Indexed(unique = true)
private String name;
private B embed;
}
B.java
@Document(collection="docsB")
public class B {
@Id
private String id;
@Indexed(unique = true)
private String name;
}
Сохраняющиеся операции:
B b = new B();
b.setName("BName1");
docsBRepository.save(b);
A a1 = new A();
a1.setName("AName1");
a1.setB(b);
docsARepository.save(a1); // stored
A a2 = new A();
a2.setName("AName2");
a2.setB(b);
docsARepository.save(a2); // dup key error
2 ответа
Я делаю тест со своей стороны с вашими документами и использую этот конфиг.
public interface DocsARepository extends MongoRepository<A,Long>{}
public interface DocsBRepository extends MongoRepository<B,Long>{}
Этот весенний конфиг
<mongo:mongo id="mongo" />
<mongo:repositories base-package="spring.mongodb.repositories"/>
И этот тест
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "spring.xml")
public class Launcher {
@Autowired
DocsBRepository docsBRepository;
@Autowired
DocsARepository docsARepository;
@Test
public void test1(){
B b = new B();
b.setName("BName1");
b = docsBRepository.save(b);
A a1 = new A();
a1.setName("AName1");
a1.setB(b);
docsARepository.save(a1); // stored
A a2 = new A();
a2.setName("AName2");
a2.setB(b);
docsARepository.save(a2); //Dont get any error but record is not inserted
}
}
После запуска теста я обнаружил, что объект a2 не вставляется в базу данных, не совсем уверен, что именно вызвало такое поведение, но если я добавлю @Reference поверх частного поля B, это будет работать как шарм.
> db.docsA.find().pretty()
{
"_id" : ObjectId("5717acb720e54e20a4d96517"),
"_class" : "com.koitoer.spring.mongodb.domain.A",
"name" : "AName1",
"b" : {
"_id" : ObjectId("5717acb720e54e20a4d96516"),
"name" : "BName1"
}
}
{
"_id" : ObjectId("5717acb720e54e20a4d96518"),
"_class" : "com.koitoer.spring.mongodb.domain.A",
"name" : "AName2",
"b" : {
"_id" : ObjectId("5717acb720e54e20a4d96516"),
"name" : "BName1"
}
}
Мой совет, который вы пытаетесь использовать в классе А
@Reference
private B b;
С помощью
<org.mongodb.version>1.5.5.RELEASE</org.mongodb.version>
<org.mongodb.driver>3.0.0-beta3</org.mongodb.driver>
<spring-framework.version>3.2.5.RELEASE</spring-framework.version>
Добавление этого рабочего примера в github
Вы не можете сделать это способом, основанным на аннотациях, но вы можете достичь этого программно, добавив такой Spring's @Configuration:
@Configuration
@DependsOn("mongoTemplate")
public class CollectionsConfig {
@Autowired
private MongoTemplate mongoTemplate;
@PostConstruct
public void initIndexes() {
mongoTemplate.indexOps("docsB") // so index is applied only to "docsB" collection
.ensureIndex(
new Index().on("name", Sort.Direction.ASC)
);
}
}