【问题标题】:Micronaut data issue with Many-to-Many relationship NOT returning nested DTOs多对多关系不返回嵌套 DTO 的 Micronaut 数据问题
【发布时间】:2020-04-25 11:09:36
【问题描述】:

我是 Micronaut 的新手,我一直在按照文档设置一个简单的 REST 应用程序。我想我会从一个简单的多对多关系开始。一切似乎都在工作。数据库表在启动时正确生成,并且端点正在返回可分页项,但不是嵌套的 Offer 列表,即使我包含了一个 Eager fetch 注释。我错过了什么? :-( 我不知道为什么。

这就是我所拥有的......

物品控制器:

@Get(value = "/{?args*}")
    public Page<ItemDTO> list(@Valid Pageable args) {
        return itemRepository.findAllOrderByName(Pageable.from(args.getNumber(), args.getSize(), args.getSort() ));
    }

物品实体:

@Entity
@Table(name = "item")
public class Item {

    public Item() {}

    public Item(@NotNull String name) {
        this.name = name;
    }

    public static ItemDTO toDTO(Item item) {
        return new ItemDTO(item);
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Version
    private Long version;

    @NotNull
    @Column(name = "name", nullable = false, unique = true)
    private String name;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
            name = "item_offer",
            joinColumns = @JoinColumn(name = "item_id"),
            inverseJoinColumns = @JoinColumn(name = "offer_id"))
    private Set<Offer> offers = new HashSet<>();

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public Set<Offer> getOffers() {
        return offers;
    }

    public Item setOffers(Set<Offer> offers) {
        this.offers = offers;
        return this;
    }

    public Item addOffer(Offer offer) {
        offers.add(offer);
        offer.getItems().add(this);
        return this;
    }

}

项目 DTO:

@Introspected
public class ItemDTO {

    @NotNull
    private String name;

    private Set<OfferDTO> offers = new HashSet<>();

    public ItemDTO() {
    }

    public ItemDTO(String name) {
        this.name = name;
    }

    public ItemDTO(Item item) {
        this.name = item.getName();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

报价实体:

@Entity
@Table(name = "offer")
public class Offer {

    public Offer() { }

    public Offer(String name) {
        this.name = name;
    }

    public static OfferDTO toDTO(Offer offer) {
        return new OfferDTO(offer);
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Version
    private Long version;

    @Column(name = "name", nullable = false, unique = true)
    private String name;

    @ManyToMany(mappedBy = "offers", fetch = FetchType.EAGER)
    private Set<Item> items = new HashSet<>();

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getVersion() {
        return version;
    }

    public void setVersion(Long version) {
        this.version = version;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Item> getItems() {
        return items;
    }

    public void setItems(Set<Item> items) {
        this.items = items;
    }
}

提供 DTO:

@Introspected
public class OfferDTO {

    @NotNull
    private String name;

    public OfferDTO() {
    }

    public OfferDTO(String name) {
        this.name = name;
    }

    public OfferDTO(Offer offer) {
        this.name = offer.getName();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

ItemRepository:

import io.micronaut.data.model.Page;
import io.micronaut.data.model.Pageable;
import io.micronaut.data.repository.PageableRepository;
import knitwizzs.domains.Item;
import knitwizzs.dtos.ItemDTO;

public interface ItemRepository extends PageableRepository<Item, Long> {

    Page<ItemDTO> findAllOrderByName(Pageable pageable);

}

这是我得到的输出:

{
"content": [
{
"name": "Item name one"
},
{
"name": "Item name two"
}
],
"pageable": {
"number": 0,
"sort": {
"sorted": false
},
"size": 100,
"offset": 0,
"sorted": false
},
"totalSize": 2,
"totalPages": 1,
"empty": false,
"size": 100,
"offset": 0,
"pageNumber": 0,
"numberOfElements": 2
}

所以没有嵌套报价的迹象?

就是这样。当我使用 Micronaut 数据时,我认为它会起作用。显然我错过了什么。

提前感谢您提供任何有用的信息。

【问题讨论】:

  • 可以添加itemRepository的代码吗?通常存储库返回实体类型,但您的存储库似乎返回 ItemDTO。那么 entity -> dto 之间的映射在哪里发生?
  • Hi Micronaut 会在您使用 Introspected 注释 DTO 时自动映射到 dto 等效项。
  • 也添加我的项目存储库,但这只是使用额外的查找方法扩展可分页存储库。
  • 哦刚刚发现了这个...github.com/micronaut-projects/micronaut-data/issues/184 :-( :-(

标签: java micronaut micronaut-data


【解决方案1】:

@JsonIgnore 注释将从 JSON 输出中排除该字段,因为它在序列化过程中被有效地忽略。

因此,您只需将 ItemDTO 类中的字段更改为:

@JsonIgnore
private Set<OfferDTO> offers = new HashSet<>();

到:

private Set<OfferDTO> offers = new HashSet<>();

【讨论】:

  • 嗨@Pieterjan Deconinck。感谢您的回复 - 抱歉,是的,只是注意到我把它留在里面了。取出它,重建项目并运行不会改变输出。我仍然没有看到任何优惠:-(
  • 您是否已经检查了对存储库的调用是否返回了报价?它可能是从存储库中获取数据的问题,也可能是序列化数据的问题。所以我会先检查存储库,以确保它的行为符合您的预期。
  • 是的,已经检查了报价是否被退回,而且确实如此。我将返回类型返回给 Item 和 Offer 的实体,并输出预期的结果。我认为这证实了嵌套 DTO 存在问题。不是我想要的解决方案,因为我希望能够通过使用 DTO 从属性中轻松挑选。我相信 Graeme Rocher 正在考虑在此处讨论此功能... github.com/micronaut-projects/micronaut-data/issues/184
猜你喜欢
  • 2016-10-26
  • 1970-01-01
  • 2019-01-24
  • 2017-07-11
  • 1970-01-01
  • 2023-03-31
  • 2014-10-14
  • 1970-01-01
相关资源
最近更新 更多