2016-07-20 3 views
2

Ich versuche, eine Springboot-Anwendung mit MongoDB und einem Rest-Controller zu erstellen und verbinden Objekte mit DBRef anstelle von klassischen Jpa-Annotationen wie OneToMany usw. Der Zweck ist, alle Lesezeichen für ein bestimmtes Konto zu drucken. Die Liste der Lesezeichen wird durch den Benutzernamen gefunden, aber es scheint, dass es nicht funktioniert.Wie man relationales Mapping zwischen Entitäten mit mongoDB in sprinboot macht?

Das sind meine Klassen:

@Document 
public class Account { 
    @DBRef 
    private Set<Bookmark> bookmarkSet = new HashSet<>(); 

    @Id 
    private String id; 

    @JsonIgnore 
    private String username; 
    private String password; 

    public Account(String username, String password) { 
     this.username = username; 
     this.password = password; 
    } 

    public void setBookmarkSet(Set<Bookmark> bookmarkSet) { 
     this.bookmarkSet = bookmarkSet; 
    } 

    public String getId() { 
     return id; 
    } 
} 

@Document 
public class Bookmark { 

    @DBRef 
    @JsonIgnore 
    private Account account; 

    @Id 
    private String id; 

    private String uri; 
    private String description; 

    public Bookmark(Account account, String uri, String description) { 
     this.account = account; 
     this.uri = uri; 
     this.description = description; 
    } 

    public Account getAccount() { 
     return account; 
    } 

    public String getId() { 
     return id; 
    } 

    public String getUri() { 
     return uri; 
    } 

    public String getDescription() { 
     return description; 
    } 
} 

Repositories:

public interface AccountRepository extends MongoRepository<Account, Long> { 
    Optional<Account> findOneByUsername(String username); 
} 

public interface BookmarkRepository extends MongoRepository<Bookmark, Long> { 
    Collection<Bookmark> findByAccountUsername(String username); 
} 

Und RestController:

@RestController 
@RequestMapping("/{userId}/bookmarks") 
public class BookmarkRestController { 
    private final AccountRepository accountRepository; 
    private final BookmarkRepository bookmarkRepository; 

    @Autowired 
    public BookmarkRestController(AccountRepository accountRepository, BookmarkRepository bookmarkRepository) { 
     this.accountRepository = accountRepository; 
     this.bookmarkRepository = bookmarkRepository; 
    } 

    @RequestMapping(value = "/{bookmarkId}", method = RequestMethod.GET) 
    Bookmark readBookmark(@PathVariable String userId, @PathVariable Long bookmarkId) { 
     this.validateUser(userId); 
     return bookmarkRepository.findOne(bookmarkId); 
    } 

    @RequestMapping(method = RequestMethod.GET) 
    Collection<Bookmark> readBookmarks(@PathVariable String userId) { 
     this.validateUser(userId); 
     return this.bookmarkRepository.findByAccountUsername(userId); 
    } 

    private void validateUser(String userId) { 
     this.accountRepository.findOneByUsername(userId).orElseThrow(() -> new UserNotFoundException(userId)); 
    } 
} 

Nachdem ich die Anwendung ausführen ich diesen Fehler:

Invalid path reference account.username! Associations can only be pointed to directly or via their id property! 

Antwort

1

Ich bin mir nicht sicher, ob Sie das richtige Schemadesign haben. Ich nehme an, dass Sie Ihre Objekte basierend auf einem relationalen Datenbanktypmodell modelliert haben, bei dem die Daten normalisiert sind und Daten über mehrere Tabellen verteilt sind, wobei Beziehungen mithilfe von IDs erfasst werden. Mit MongoDB können Sie Ihre Daten mit der Hierarchie, die einfach in dem einen Dokument enthalten ist, strukturieren und speichern.

Also in Ihrem Beispiel wäre das Lesezeichen kein Dokument selbst, sondern wäre ein Unterdokument des Kontos. Entfernen Sie die @Document Annotation aus dem Bookmark-Objekt und die @DBRef Annotationen und speichern Sie die Bookmarks einfach im Account-Dokument.

Dies würde Ihnen ein Schema eher wie dieses:

{ 
    "_id": 1, 
    "bookmarkSet": [ 
    { 
     "uri": "http://www.foo.com", 
     "description": "foo" 
    }, 
    { 
     "uri": "http://www.bar.com", 
     "description": "bar" 
    } 
    ], 
    "username": "John", 
    "password": "password" 
} 

* Hinweis: Wenn Sie die Lesezeichen Unterlagen machen können Sie das _id Mitglied aus dem Objekt Lesezeichen entfernen

Der beste Entwurf hängt Wie viele Lesezeichen erwarten Sie von jedem Konto? Wenn es nur ein paar Lesezeichen ist, dann würde das, was ich vorgeschlagen habe, gut funktionieren. Wenn Sie Tausende haben, möchten Sie es möglicherweise anders strukturieren. Es gibt viele Artikel über Schemadesign in der NoSQL-Datenbank. Dieser deckt die Optionen für Subdokumente recht gut Einbetten: http://blog.mongodb.org/post/87200945828/6-rules-of-thumb-for-mongodb-schema-design-part-1

+0

Aber wie sie zu speichern, wenn ich 1000 Lesezeichen haben, wäre es verrückt sein, um sie manuell zu speichern. Ich sollte Autowire verwenden? oder wie genau? – Gustavo

+0

Ich habe meine Antwort aktualisiert. Prost – robjwilkins

Verwandte Themen