2013-07-28 16 views
12

Używam Spring-danych dla MongoDB:Wiosna -Data MongoDB problem z pola, który jest interfejsem

Informacje o wersji - wersja org.mongodb.mongo-java-kierowca 2.10.1, org.springframework. data.spring-data-mongodb wersja 1.2.1.RELEASE.

Mam sprawę, która jest podobna do tej określonej w here, który jest (przepraszam za formatowania ...):

Właśnie rozpoczęła prace jakąś aplikację w Javie z wiosny-data-MongoDB i natknąłem się jakiś problem, który nie byłem w stanie rozwiązać:

mam kilka ziaren dokumentu takiego:

@Document(collection="myBeanBar") 
public class BarImpl implements Bar { 
    String id; 
    Foo foo; 
    // More fields and methods ... 
} 

@Document 
public class FooImpl implements Foo { 
    String id; 
    String someField; 
    // some more fields and methods ... 
} 

I mam repozytorium klasę z metodą, która po prostu wywołuje znaleźć podobny do tym:

public List<? extends Bar> findByFooField(final String fieldValue) { 
    Query query = Query.query(Criteria.where("foo.someField").is(fieldValue)); 
    return getMongoOperations().find(query, BarImpl.class); 
} 

Zapisywanie Bar działa dobrze, to zapisz go w Mongo wraz z Atrybut "_class" dla Foo i Bar. Jednak znalezienie przez jakiś atrybutu w Foo będzie wyjątek takiego:

Exception in thread "main" java.lang.IllegalArgumentException: No 
property someField found on test.Foo! 
    at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentPropertyPath(AbstractMappingContext.java:225) 
    at org.springframework.data.mongodb.core.convert.QueryMapper.getPath(QueryMapper.java:202) 
    at org.springframework.data.mongodb.core.convert.QueryMapper.getTargetProperty(QueryMapper.java:190) 
    at org.springframework.data.mongodb.core.convert.QueryMapper.getMappedObject(QueryMapper.java:86) 
    at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:1336) 
    at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:1322) 
    at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:495) 
    at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:486) 

Rozwiązanie, które zostało wydane było użyć adnotacji @TypeAlias ​​na abstrakcyjne klasy, który powiedział ramy używać specyficzny implementacja (w tym przypadku FooImpl).

W moim przypadku, mam interfejsu członków, zamiast abstrakcyjnych członków:

@Document(collection="myBeanBar") 
public class BarImpl implements Bar { 
    String id; 
    IFoo foo; 
    // More fields and methods ... 
} 

Jestem bardzo niechętnie umieścić adnotację na interfejsie IFoo które dadzą domyślną implementację , zamiast tego chciałbym powiedzieć, co to domyślna implementacja domyślnej implementacji w kontekście implementacji klasy BarImpl , podobnej do @JsonTypeInfo:

@Document(collection="myBeanBar") 
public class BarImpl implements Bar { 
    String id;  

    @JsonTypeInfo(use = Id.CLASS, defaultImpl = FooImpl.class) 
    IFoo foo; 

    // More fields and methods ... 
} 

Znalazłem this answer, który mniej więcej mówi, aby unikać używania interfejsów. ale z przyjemnością dowiem się, czy nie ma lepszej opcji.

Wszelkie pomysły?

Dzięki!

+0

Którą wersję Spring Data MongoDB używasz? –

+0

Po prawej, dodałem informację o wersji - org.mongodb.mongo-java-driver wersja 2.10.1, org.springframework.data.spring-data-mongodb wersja 1.2.1.RELEASE. –

+2

Wygląda na to, że natknąłeś się na https://jira.springsource.org/browse/DATACMNS-311. Czy masz Spring Data Commons 1.5.1 na ścieżce klas? To jest wersja, w której błąd został naprawiony. –

Odpowiedz

0

To naprawdę zły pomysł, aby zdefiniować interfejsy jako pole w obiekcie danych.

Interfejs oznacza możliwość jakiegoś obiektu do zrobienia czegoś, ale nie podaje żadnych informacji o polach. Czy naprawdę potrzebujesz korzystać z interfejsów? Czy możesz tego uniknąć? Nawet użycie abstrakcyjnej definicji klasy będzie lepszym pomysłem.

P.S. poza kursem moja odpowiedź nie może być w żadnym wypadku oznaczona jako poprawna odpowiedź.

5

Mój problem jest podobny do pytania, ale wyjątek rzucony jest nieco inna:

Could not instantiate bean class [class name]: Specified class is an interface 

Dzieje się tak, gdy jedna z dziedzin mojej klasie DB jest zadeklarowana jako interfejs. Zapisanie tego pola jest w porządku, ale wyjątek jest generowany podczas odczytu z MongoDB. W końcu znalazłem rozwiązanie, które wykorzystuje org.springframework.core.convert.converter.Converter.

DWIE kroki do wykonania, 1. skonstruuj klasę, która implementuje Converter; 2. Zarejestruj konwerter w kontekście serwletu. TAK, nie trzeba modyfikować żadnego istniejącego kodu, takiego jak dodanie adnotacji.

Poniżej jest moje klasy modelu, gdzie pole Data to interfejs:

@Document(collection="record") 
public class Record { 
    @Id 
    private String id; 

    // Data is an interface 
    private Data data; 

    // And some other fields and setter/getter methods of them 
} 

Przetwornik:

@ReadingConverter 
public class DataReadConverter implements Converter<DBObject, Data> { 
    @Override 
    public Data convert(DBObject source) { 
     // Your implementation to parse the DBObject, 
     // this object can be BasicDBObject or BasicDBList, 
     // and return an object instance that implements Data. 

     return null; 
    } 
} 

Ostatnią rzeczą do zrobienia jest, aby zarejestrować konwerter, moja konfiguracja jest w xml:

<mongo:mongo id="mongo" /> 

<mongo:db-factory mongo-ref="mongo" dbname="example" /> 

<mongo:mapping-converter> 
    <mongo:custom-converters> 
     <mongo:converter> 
      <beans:bean class="com.example.DataReadConverter" /> 
     </mongo:converter> 
    </mongo:custom-converters> 
</mongo:mapping-converter> 

<beans:bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> 
    <beans:constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> 
    <beans:constructor-arg name="mongoConverter" ref="mappingConverter" /> 
</beans:bean> 

Wdróż aplikację i spróbuj ponownie. Powinien poprawnie przeanalizować obiekt DBObject z MongoDB w polu interfejsu.

Wersja mojej aplikacji Spring MongoDB to: wiosna - * - 4.1.0 i spring-data-mongodb-1.6.0.

Powiązane problemy