AndyRED
AndyRED

Reputation: 361

Micronaut data issue with Many-to-Many relationship NOT returning nested DTOs

I am new to Micronaut, and I have been following the documentation to set up a simple REST application. I thought I would start with a simple Many-to-Many relationship. Everything seemed to be working. The Database tables are being generated at startup correctly, and the endpoint is returning the pageable items but NOT the nested list of Offers even though I'm including an eager fetch annotation. What am I missing? :-( I can not figure out why.

Here's what I have...

Item Controller:

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

Item Entity:

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

}

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

}

Offer Entity:

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

Offer 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);

}

This is the output I'm getting:

{
"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
}

So no sign of the nested offers?

That's it. As I'm utilising Micronaut data, I assumed it would work. Obviously I have missed something.

Thank you in advance for any helpful information.

Upvotes: 3

Views: 2317

Answers (1)

Pieterjan Deconinck
Pieterjan Deconinck

Reputation: 552

The @JsonIgnore annotation will exclude this field from the JSON output, since it is effectively ignored during serialization.

So you can just change your field in the ItemDTO class from:

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

to:

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

Upvotes: 1

Related Questions