Saya akan menjawab pertanyaan saya sendiri. Seperti disebutkan dalam komentar, solusinya adalah menggunakan Converter
.
Berikut adalah contoh dari apa yang ingin saya capai dengan model kelas saya :
Contact
dapat berupa Person
atau Organisation
.
Jika Anda menggunakan spring-data-mongodb MongoRepository
untuk menulis data dalam database Anda sesuai dengan model entitas Anda, sebuah _class
bidang akan ditambahkan ke akar dokumen dan ke jenis properti kompleks (lihat bagian ini
). Bidang ini menyimpan nama kelas Java yang sepenuhnya memenuhi syarat dan memungkinkan disambiguasi saat memetakan dari Dokumen MongoDb ke model data Spring.
Jika aplikasi Anda baru saja membaca dokumen dari database (tidak ada _class
bidang), Anda perlu memberi tahu data Spring kelas mana yang akan dipakai saat memetakan Contact
. Spring-data memungkinkan Anda untuk menyesuaikan perilaku pemetaan tipe default menggunakan Converter
. Menggunakan Converter
eksplisit mengganti default pemetaan untuk kelas
. Anda perlu secara eksplisit memetakan seluruh kelas Anda. Berikut adalah contoh ContactReadConverter my saya :
@ReadingConverter
public class ContactReadConverter implements Converter<Document, Contact> {
@Override
public Contact convert(Document source) {
if (source.get("firstName") == null) {
Organisation organisation = new Organisation();
I18n name = new I18n();
name.setEn(source.get("name", Document.class).get("en", String.class));
name.setFr(source.get("name", Document.class).get("fr", String.class));
organisation.setName(name);
organisation.setAcronym(source.get("acronym", String.class));
organisation.setRole(source.get("role", String.class));
return organisation;
}
Person person = new Person();
person.setFirstName(source.get("firstName", String.class));
person.setLastName(source.get("lastName", String.class));
person.setRole(source.get("role", String.class));
person.setEmail(source.get("email", String.class));
person.setOrcId(source.get("orcId", String.class));
if (source.get("organisation") != null) {
Document sourceOrg = source.get("organisation", Document.class);
Organisation organisation = new Organisation();
organisation.setAcronym(sourceOrg.get("acronym", String.class));
organisation.setRole(sourceOrg.get("role", String.class));
if (sourceOrg.get("name") != null) {
I18n name = new I18n();
name.setFr(sourceOrg.get("name", Document.class).get("fr", String.class));
name.setEn(sourceOrg.get("name", Document.class).get("en", String.class));
organisation.setName(name);
}
person.setOrganisation(organisation);
}
return person;
}
}
Kemudian, konverter yang baru ditentukan perlu didaftarkan:
@Configuration
public class DataportalApplicationConfig extends AbstractMongoConfiguration {
@Value("${spring.data.mongodb.uri}")
private String uri;
@Value("${spring.data.mongodb.database}")
private String database;
@Override
public MongoClient mongoClient() {
return new MongoClient(new MongoClientURI(uri));
}
@Override
protected String getDatabaseName() {
return database;
}
@Bean
@Override
public MongoCustomConversions customConversions() {
List<Converter<?, ?>> converterList = new ArrayList<>();
converterList.add(new ContactReadConverter());
return new MongoCustomConversions(converterList);
}
}
Semoga membantu.