Frage

Die Standard - MappingMongoConverter fügt einen benutzerdefinierten Typ-Schlüssel ("_class") auf jedes Objekt in der Datenbank.Also, wenn ich eine Person:

package my.dto;
public class Person {
    String name;
    public Person(String name) {
        this.name = name; 
    }
}

und speichern Sie es auf die db:

MongoOperations ops = new MongoTemplate(new Mongo(), "users");
ops.insert(new Person("Joe"));

das resultierende Objekt wird in der mongo wird:

{ "_id" : ObjectId("4e2ca049744e664eba9d1e11"), "_class" : "my.dto.Person", "name" : "Joe" }

Fragen:

  1. Was sind die Auswirkungen von moving die Person-Klasse in einem anderen namespace?

  2. Ist es möglich, nicht zu verschmutzen das Objekt mit der "_class" - Taste;ohne schreiben einer einzigartigen Konverter nur für die Person-Klasse?

War es hilfreich?

Lösung

Hier ist also die Geschichte: Wir fügen den Typ standardmäßig als Hinweis hinzu, welche Klasse wir tatsächlich instanziieren sollen. Wie Sie in einen Typ putzen müssen, um das Dokument in via zu lesen MongoTemplate Auf jeden Fall gibt es zwei mögliche Optionen:

  1. Sie übergeben einen Typ. Der tatsächliche gespeicherte Typ kann zugewiesen werden. In diesem Fall betrachten wir den gespeicherten Typ, verwenden Sie ihn für die Erstellung von Objekten. Klassisches Beispiel Hier legt polymorphe Abfragen. Angenommen, Sie haben eine abstrakte Klasse Contact und dein Person. Sie könnten dann nachfragen Contacts und wir im Wesentlichen müssen, zu ... haben Bestimmen Sie einen zum Instanziieren von einem Typ.
  2. Wenn Sie - andererseits - in einen völlig anderen Typ übergeben, haben wir einfach in diesen gegebenen Typ eingetaucht, nicht in das, das tatsächlich im Dokument gespeichert ist. Das würde Ihre Frage behandeln, was passiert, wenn Sie den Typ verschieben.

Sie könnten anschauen diese Karte Dies deckt eine Art steckbarer Typ -Mapping -Strategie ab, um die Typinformationen in einen tatsächlichen Typ zu verwandeln. Dies kann einfach Platzeinsparungszwecken dienen, da Sie möglicherweise einen langen qualifizierten Klassennamen auf einen Hash mit wenigen Buchstaben reduzieren möchten. Es würde auch komplexere Migrationsszenarien ermöglichen, in denen Sie möglicherweise vollständig willkürliche Typen finden, die von einem anderen DataStore -Client erstellt und an Java -Typen binden.

Andere Tipps

Hier ist meine Annotation und es funktioniert.

@Configuration
public class AppMongoConfig {

    public @Bean
    MongoDbFactory mongoDbFactory() throws Exception {
        return new SimpleMongoDbFactory(new Mongo(), "databasename");
    }

    public @Bean
    MongoTemplate mongoTemplate() throws Exception {

        //remove _class
        MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory(), new MongoMappingContext());
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));

        MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory(), converter);

        return mongoTemplate;

    }

}
<mongo:mongo host="hostname" port="27017">
<mongo:options
...options...
</mongo:mongo>
<mongo:db-factory dbname="databasename" username="user" password="pass"                     mongo-ref="mongo"/>
<bean id="mongoTypeMapper"     class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper">
<constructor-arg name="typeKey"><null/></constructor-arg>
</bean>
<bean id="mongoMappingContext"      class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" />
<bean id="mongoConverter"     class="org.springframework.data.mongodb.core.convert.MappingMongoConverter">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
<constructor-arg name="mappingContext" ref="mongoMappingContext" />
<property name="typeMapper" ref="mongoTypeMapper"></property>
</bean>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
<constructor-arg name="mongoConverter" ref="mongoConverter" />
<property name="writeResultChecking" value="EXCEPTION" /> 
</bean>

Wenn Sie möchten, zu deaktivieren _class Attribut standardmäßig, aber bewahren Polymorphismus für bestimmte Klassen können Sie ausdrücklich definieren, welche Art von _class (optional) Feld von configuing:

@Bean
public MongoTemplate mongoTemplate() throws Exception {
    Map<Class<?>, String> typeMapperMap = new HashMap<>();
    typeMapperMap.put(com.acme.domain.SomeDocument.class, "role");

    TypeInformationMapper typeMapper1 = new ConfigurableTypeInformationMapper(typeMapperMap);

    MongoTypeMapper typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Arrays.asList(typeMapper1));
    MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory(), new MongoMappingContext());
    converter.setTypeMapper(typeMapper);

    MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory(), converter);
    return mongoTemplate;
}

Dies wird beibehalten _class Feld (oder wie auch immer du Sie nennen willst in construtor) für die nur die angegebenen Personen.

Sie können auch das schreiben eigener TypeInformationMapper beispielsweise auf Basis von annotations.Wenn Sie Ihr Dokument mit Anmerkungen versehen von @DocumentType("aliasName") Sie halten Polymorphismus indem alias der Klasse.

Ich habe kurz erklärt es auf meinem blog, aber hier ist ein Stück von quick-code:https://gist.github.com/athlan/6497c74cc515131e1336

Während Mkyongs Antwort immer noch funktioniert, möchte ich meine Lösung Version hinzufügen, da nur wenige Bits veraltet sind und möglicherweise kurz vor der Aufräumarbeiten stehen.

Zum Beispiel : MappingMongoConverter(mongoDbFactory(), new MongoMappingContext()) ist veraltet zugunsten von new MappingMongoConverter(dbRefResolver, new MongoMappingContext()); und SimpleMongoDbFactory(new Mongo(), "databasename"); zugunsten new SimpleMongoDbFactory(new MongoClient(), database);.

Meine endgültige bearbeitete Antwort ohne Abschaltungswarnungen lautet:

@Configuration
public class SpringMongoConfig {

    @Value("${spring.data.mongodb.database}")
    private String database;

    @Autowired
    private MongoDbFactory mongoDbFactory;

    public @Bean MongoDbFactory mongoDBFactory() throws Exception {
        return new SimpleMongoDbFactory(new MongoClient(), database);
    }

    public @Bean MongoTemplate mongoTemplate() throws Exception {

        DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory);

        // Remove _class
        MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext());
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));

        return new MongoTemplate(mongoDBFactory(), converter);

    }

}

Ich hoffe, dies hilft Menschen, die eine saubere Klasse ohne Abschaltwarnungen haben möchten.

Dies ist meine Lösung mit einer Zeilen:

@Bean 
public MongoTemplate mongoTemplateFraud() throws UnknownHostException {

  MongoTemplate mongoTemplate = new MongoTemplate(getMongoClient(), dbName);
  ((MappingMongoConverter)mongoTemplate.getConverter()).setTypeMapper(new DefaultMongoTypeMapper(null));//removes _class
  return mongoTemplate;
}

Ich hatte lange mit diesem Problem zu kämpfen. Ich folgte dem Ansatz von Mkyong Aber als ich a vorstellte LocalDate Attribut (jede JSR310 -Klasse von Java 8) Ich habe die folgende Ausnahme erhalten:

org.springframework.core.convert.ConverterNotFoundException:
No converter found capable of converting from type [java.time.LocalDate] to type [java.util.Date]

Der entsprechende Konverter org.springframework.format.datetime.standard.DateTimeConverters ist Teil des Frühjahrs 4.1 und wird in den Federdaten MongoDB 1.7 verwiesen. Auch wenn ich neuere Versionen verwendet habe, sprang der Konverter nicht hinein.

Die Lösung bestand darin, die vorhandenen zu verwenden MappingMongoConverter und nur eine neue zur Verfügung stellen DefaultMongoTypeMapper (Der Code von Mkyong steht unter Kommentar):

@Configuration
@EnableMongoRepositories
class BatchInfrastructureConfig extends AbstractMongoConfiguration
{
    @Override
    protected String getDatabaseName() {
        return "yourdb"
    }

    @Override
    Mongo mongo() throws Exception {
        new Mongo()
    }

    @Bean MongoTemplate mongoTemplate()
    {
        // overwrite type mapper to get rid of the _class column
//      get the converter from the base class instead of creating it
//      def converter = new MappingMongoConverter(mongoDbFactory(), new MongoMappingContext())
        def converter = mappingMongoConverter()
        converter.typeMapper = new DefaultMongoTypeMapper(null)

        // create & return template
        new MongoTemplate(mongoDbFactory(), converter)
    }

Zusammenfassen:

  • erweitern AbstractMongoConfiguration
  • Annotate mit EnableMongoRepositories
  • in mongoTemplate Get Converter aus der Basisklasse, dies stellt sicher, dass die Typ -Conversion -Klassen registriert sind

Sie müssen nur die @typealias -Annotation zur Klassendefinition hinzufügen, um den Typ Mapper zu ändern

@Configuration
public class MongoConfig {

    @Value("${spring.data.mongodb.database}")
    private String database;

    @Value("${spring.data.mongodb.host}")
    private String host;

    public @Bean MongoDbFactory mongoDbFactory() throws Exception {
        return new SimpleMongoDbFactory(new MongoClient(host), database);
    }

    public @Bean MongoTemplate mongoTemplate() throws Exception {

        MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory()),
                new MongoMappingContext());
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));

        MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory(), converter);

        return mongoTemplate;

    }

}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top