Java 如何在sprinboot中使用mongoDB在实体之间进行关系映射?

Java 如何在sprinboot中使用mongoDB在实体之间进行关系映射?,java,mongodb,spring-boot,Java,Mongodb,Spring Boot,我正在尝试使用MongoDB和Rest控制器创建一个springboot应用程序,并使用DBRef将对象连接在一起,而不是像OneToMany等经典Jpa注释。目的是打印特定帐户的所有书签。书签列表是通过用户名找到的,但似乎不起作用 这些是我的课程: @Document public class Account { @DBRef private Set<Bookmark> bookmarkSet = new HashSet<>(); @Id

我正在尝试使用MongoDB和Rest控制器创建一个springboot应用程序,并使用DBRef将对象连接在一起,而不是像OneToMany等经典Jpa注释。目的是打印特定帐户的所有书签。书签列表是通过用户名找到的,但似乎不起作用

这些是我的课程:

@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;
    }
}

我不确定您是否有正确的模式设计。我假设您已经基于关系数据库类型模型对对象进行了建模,在该模型中,数据被标准化,数据被分割到多个表中,并使用id捕获关系。使用MongoDB,您可以通过一个文档中包含的继承权来构造和存储数据

因此,在您的示例中,书签不是文档本身,而是帐户的子文档。从Bookmark对象中删除
@Document
注释和
@DBRef
注释,只需将书签存储在Account文档中即可

这将为您提供一个更像这样的模式:

{
  "_id": 1,
  "bookmarkSet": [
    {
      "uri": "http://www.foo.com",
      "description": "foo"
    },
    {
      "uri": "http://www.bar.com",
      "description": "bar"
    }
  ],
  "username": "John",
  "password": "password"
}
*注意:如果创建书签子文档,则可以从书签对象中删除_id成员

最好的设计将取决于您希望每个帐户拥有多少书签。如果只有几个书签,那么我的建议会很好。如果你有几千个,那么你可能想用不同的结构。关于NoSQL数据库中模式设计的文章很多。这一部分很好地介绍了嵌入子文档的选项:

但是如何存储它们如果我有1000个书签,手动存储它们会很疯狂。我应该用自动线吗?或者确切地说如何?
@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));
    }
}
Invalid path reference account.username! Associations can only be pointed to directly or via their id property!
{
  "_id": 1,
  "bookmarkSet": [
    {
      "uri": "http://www.foo.com",
      "description": "foo"
    },
    {
      "uri": "http://www.bar.com",
      "description": "bar"
    }
  ],
  "username": "John",
  "password": "password"
}