2

I am on my first Quarkus project based on quarkus-resteasy-reactive.

I have managed so far to get the basic operations working but I'm stuck on recording linked information in many to many.

Basically I have a :

@Entity
@Cacheable
public class Fiestar extends PanacheEntity {

    @Column(length = 250, unique = true, nullable = false)
    public String mail;

    @Column(length = 50, unique = true, nullable = false)
    public String phone;

    @Column(length = 150, unique = true)
    public String nickname;

    @Column(length = 250, nullable = false)
    public String password;

    @Column(length = 250)
    public String salt;

    @ManyToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER)
    @JoinTable(name = "fiesta_fiestar",
            joinColumns = @JoinColumn(name = "fiestar_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "fiesta_id", referencedColumnName = "id"))
    public List<Fiesta> fiestasInvite;

    @Column
    public boolean isRememberToday = true;

    @Column
    public boolean isRememberDayBefore = false;

    @Column
    public boolean isRememberWeekBefore = false;

    @Column
    public boolean isAdmin = false;

    @Column
    public String calendarId;

    public Fiestar(Long id) {
        this.id = id;
    }

    public Fiestar() {
    }
}

and an entity:

@Entity
@Cacheable
public class Fiesta extends PanacheEntity {

    @Column(length = 250, nullable=false)
    public String title;

    @Column(nullable = false)
    public LocalDateTime startDate;

    @Column
    public LocalDateTime endDate;

    @Column
    public String address;

    @Column(length = 500)
    public String description;

    @JoinColumn(name = "creator_id")
    @ManyToOne
    public Fiestar creator;

    @ManyToMany(mappedBy = "fiestasInvite", fetch = FetchType.EAGER)
    public List<Fiestar> guests;

    public Fiesta(Long id) {
        this.id = id;
    }

    public Fiesta() {
    }
}

related by the entity:

@Entity(name = "fiesta_fiestar")
@Cacheable
public class FiestaFiestar extends PanacheEntity {

    @JoinColumn(name = "fiesta_id")
    @ManyToOne
    public Fiesta fiesta;

    @JoinColumn(name = "fiestar_id")
    @ManyToOne
    public Fiestar fiestar;

    @Column
    public boolean isComing = false;

    @Column
    public boolean isMaybeComing = true;

    @Column
    public boolean isNotComing = false;

    @Column
    public boolean isTakingCar = false;

    @Column
    public boolean isAllowToInvite = false;

    @Column
    public String carFrom;
}

What I am trying to do is very basic as I am simply trying to persist a Fiesta and once that is done persist the guest list associated with it (pre-existing Fiestars).

Problem: The Fiesta is well persisted but not the relationship FiestaFiestar.

So far I have tried three methods:

  • Panach.withTransaction( =>
public Uni<Fiesta> createFiesta(FiestaDto fiesta) {
    Fiesta fiestaToPersist = fiestaMapper.toEntity(fiesta);
    Log.debug(String.format("mapped fiesta = %s", fiestaToPersist.title));
    Log.debug(String.format("Fiesta guest number %s", fiesta.getGuests().size()));
    return Panache.withTransaction(() -> fiestaToPersist.<Fiesta>persist()
                .onItem().ifNotNull().call(fiestaCreated -> {
                    Log.debug("Currently ion the call methode");
                    Log.debug("isNotEmpty(fiesta.getGuests()) " + CollectionUtils.isNotEmpty(fiesta.getGuests()));
                    Log.debug("isNotEmpty(fiesta.getShops()) " + CollectionUtils.isNotEmpty(fiesta.getShops()));
                    Log.debug("fiestaCreated.isPersistent() " + fiestaCreated.isPersistent());
                    if (CollectionUtils.isNotEmpty(fiesta.getGuests())) {
                        var fiestarIds = fiesta.getGuests().stream().map(FiestarDto::getId).toList();
                        Fiestar.<Fiestar>list("id in ?1", fiestarIds).onItem()
                                .ifNotNull()
                                .invoke(fiestars -> {
                                    Log.debug(String.format("mapping %s guests with fiesta : %s", fiestars.size(), fiestaToPersist.id));
                                    List<FiestaFiestar> guests = new ArrayList<>();
                                    fiestars.forEach(guest -> {
                                        FiestaFiestar newGuest = new FiestaFiestar();
                                        newGuest.fiesta = fiestaCreated;
                                        newGuest.fiestar = guest;
                                        guests.add(newGuest);
                                        Log.debug(String.format("Guest list : Size => %s, guest => %s", guests.size(), guest.toString()));
                                    });
                                    FiestaFiestar.persist(guests)
                                            .onItem().ifNotNull().invoke(() -> {
                                                Log.debug("One Guest is persist");
                                                fiestaCreated.guests = guests.stream().map(x -> x.fiestar).toList();
                                            })
                                            .onItem().ifNull().failWith(() -> new RuntimeException("Fail to persist guests :\\n"));
                                }).onItem().ifNull().failWith(() -> new RuntimeException("Guests not found  !"));
                    }
    }
  • Uni.createFrom() :
@WithTransaction
public Uni<Fiesta> persistEntity(FiestaDto fiestaDto) {
    Fiesta fiestaToPersist = fiestaMapper.toEntity(fiestaDto);
    Log.debug(String.format("mapped fiesta = %s", fiestaToPersist.title));
    Log.debug(String.format("Fiesta guest number %s", fiestaDto.getGuests().size()));
    return Uni.createFrom().item(() -> {
              fiestaToPersist.persist();
              if (CollectionUtils.isNotEmpty(fiestaDto.getGuests())) {
                  Log.debug(String.format("mapping %s guests with fiesta : %s", fiestaDto.getGuests().size(), fiestaToPersist.id));
                  List<FiestaFiestar> guests = new ArrayList<>();
                  fiestaDto.getGuests().forEach(guest -> {
                      var guestToAdd = new FiestaFiestar();
                      guestToAdd.fiesta = fiestaToPersist;
                      guestToAdd.fiestar = new Fiestar(guest.getId());
                      guests.add(guestToAdd);
                      Log.debug(String.format("Guest list : Size => %s, guest => %s", guests.size(), guest.getId()));
                      guestToAdd.persist();
                  });
              }
              return fiestaToPersist;
          });
  • And finally to persist first the Fiesta and then to add guests:

    public Uni<Fiesta> addGuest(GuestToAddPayload payload) {
           Panache.withTransaction(() -> {
                Fiesta.findById(payload.getFiestaId())
                        .replaceIfNullWith(() -> {
                            throw new RuntimeException("Fiesta not found");
                        }).onItem()
                        .transform(foundFiesta -> {
                            Log.debug("We got fiesta");
                            Fiestar.list()
                        })
                payload.getGuestIds().forEach(fiestarId -> {
                    FiestaFiestar guest = new FiestaFiestar();
                    guest.fiesta = new Fiesta(payload.getFiestaId());
                    guest.fiestar = new Fiestar(fiestarId);
                    guest.persist();
                });
                return null;
            }); 
        }
    

Unfortunately, all three attempts ended with the same answer... No persistent links.

So I guess I'm not using the asynchronous operation of the library correctly.

I've tried to find an example of such a relationship in the Quackus documentation.
Thanks to all !

Abra
  • 19,142
  • 7
  • 29
  • 41
MrGlup
  • 21
  • 3

0 Answers0