1

У меня есть 2 сущности, соединенные многими со многими. Шаблон должен содержать список:

владелец1

приют 1 приют 2

владелец1 приют 1

Но я не понимаю, как я могу ссылаться на таблицу ссылок, нужен ли мне третий владелец-укрытие Нужно ли создавать хранилище для таблицы соединений?

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@DynamicUpdate
@Entity
@Table(name = "owner")
public class Owner {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int idOwner;

    private String name;

    private String address;

    private String description;

    @ManyToMany(cascade = {CascadeType.ALL})
    @JoinTable(
            name = "owner_shelter",
            joinColumns = {@JoinColumn(name = "owner")},
            inverseJoinColumns = {@JoinColumn(name = "shelter")}
    )
    private Set<Shelter> shelterOwner;
}

-

@Data
@DynamicUpdate
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    @Entity
    @Table(name = "shelter")
    public class Shelter {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;

        private String name;
        private String address;
        private String description;

    @ManyToMany(mappedBy = "shelterOwner")
    private Set<Owner> sheltersOwner;
    }

пока что я могу вывести только список

    @Autowired
    ShelterRepository shelterRepository;
    @Autowired
    OwnerRepository ownerRepository;

    @GetMapping("/shelters")
    public String getPage(Authentication authentication, Model model) {
        if (authentication != null) {
            model.addAttribute("authentication", authentication);
        }
        List<Shelter> shelters = shelterRepository.findAll();
        List<Owner> owners = ownerRepository.findAll();
        model.addAttribute("shelters", shelters);
        model.addAttribute("owners", owners);
        return "shelterList";

    }
}

введите сюда описание изображения

Tanya
  • 27
  • 7
  • Могли бы вы перевести на русский? Увы, но правила сообщества так требуют( – Antonio112009 Apr 28 '20 at 13:39
  • а что по таблицам? скинь схему таблиц. Желательно скрином – Artur Vartanyan Apr 28 '20 at 13:42
  • Рассмотрете вот эту ссылку - https://ru.stackoverflow.com/a/993199/275232 – Antonio112009 Apr 28 '20 at 13:46
  • @ArturVartanyan добавила – Tanya Apr 28 '20 at 13:47
  • @Antonio112009 да, но как мне в контроллере сделать так, чтобы я могла вывести именно Владелец - приюты – Tanya Apr 28 '20 at 13:48
  • 1 - я думаю надо избавиться от Set<> и использовать List<>. 2 - Как я понимаю, у Вас bidirectional зависимость -> надо добавить методы для заполнения данных (смотрите в моей ссылке раздел ManyToMany bidirectional) – Antonio112009 Apr 28 '20 at 13:51
  • а лучше диаграмму таблиц постройте, так наглядней будет – Санаев Apr 28 '20 at 13:55
  • 3 - про ID. IDENTITY лучше не использовать. В таком случае используйте AUTO, или самому создавать таблицы с помощью SQL c использованием autoincrement или использовать кастомный autoincrement - https://ru.stackoverflow.com/q/994237/275232 – Antonio112009 Apr 28 '20 at 13:56
  • @Antonio112009 не совсем понимаю, как эти методы помогут мне вытащить из БД данные и связать их, не понимаю, как они вообще должны быть сконструированы – Tanya Apr 28 '20 at 14:02
  • https://vladmihalcea.com/the-best-way-to-use-the-manytomany-annotation-with-jpa-and-hibernate/ – Antonio112009 Apr 28 '20 at 14:04

1 Answers1

0

Объяснение:

  1. На Lombok лучше на 100% не полагаться. читать тут Item 45. и это
  2. Я заменил дублирующийся shelterOwner, потому что это не shelterOwner, а owners (это же список) и shelters (это же список).
  3. Изменил в Id IDNETITY на кастомный. Про способы генерации читать тут и мой вопрос на ruSO - тут
  4. Зачем нужны методы AddOwner, RemoveOwner, AddShelter, RemoveShelter? так как у вас (как я понял) зависимость в две стороны (bidirectional), то надо как делать рекурсию объектов, то есть объект А должен ссылаться на Б, а Б на А, А на Б и так вечно. Если просто добавить A к Б (без обратной зависимости), то у вас может и не получиться двухнаправленная зависимость. Именно таким способом мы связываем объекты между собою.
  5. Избавиться от ненужных аннотаций. Прочитайте для чего какая аннотация нужна.
  6. Про model.addAttribute("authentication", authentication);. Это лишняя строчка. Если вы хотите взять email, то вот вариант: <span th:text="${#authentication.getPrincipal().getUsername()}"></span> (для Thymeleaf). Если вам нужно отобразить данные в зависимости от уровня достпа юзера - https://www.thymeleaf.org/doc/articles/springsecurity.html

Owner.java

@Data
@AllArgsConstructor
@NoArgsConstructor
@DynamicUpdate
@Entity
@Table
public class Owner {
    @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "owner_generator")
  @SequenceGenerator(name="owner_generator", sequenceName = "owner_seq", allocationSize = 1, initialValue = 1)
    private Long id;

    private String name;

    private String address;

    private String description;

    @ManyToMany(fetch = FetchType.LAZY,
            cascade = CascadeType.ALL
    )
    @JoinTable(name = "owner_shelter",
            joinColumns = { @JoinColumn(name = "owner_id") },
            inverseJoinColumns = { @JoinColumn(name = "shelter_id") })
    private List<Shelter> shelters = new ArrayList<>();

    public void addShelter(Shelter shelter) {
      shelters.add(shelter);
      shelter.getOwners().add(this);
    }

    public void removeShelter(Shelter shelter) {
      shelters.remove(shelter);
      shelter.getOwners().remove(this);
    }
}

Shelter.java

@Data
@DynamicUpdate
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table
public class Shelter {

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "shelter_generator")
  @SequenceGenerator(name="shelter_generator", sequenceName = "shelter_seq", allocationSize = 1, initialValue = 1)
    private Long id;

  private String name;
  private String address;
  private String description;

   @ManyToMany(mappedBy = "shelters")
   private List<Owner> owners;

   public void addOwner(Owner owner) {
      owners.add(owner);
      owner.getShelters().add(this);
   }

   public void removeOwner(Owner owner) {
      owners.remove(owner);
      owner.getShelters().remove(this);
   }

  }
}

Пример добавления приютов к владельцу


    @Autowired
    ShelterRepository shelterRepository;

    @Autowired
    OwnerRepository ownerRepository;

    public void addNewShelters (){
      Shelter shelter1 = new Shelter();
      shelter1.setName("приют1");
      Shelter shelter2 = new Shelter();
      shelter2.setName("приют2");
      shelterRepository.save(shelter1);
      shelterRepository.save(shelter2);

      Owner owner = new Owner();
      owner.setName("владелец");
      owner.addShelter(shelterRepository.findByName("приют1"));
      owner.addShelter(shelterRepository.findByName("приют2"));
      ownerRepository.save(Owner);

      Owner ownerDB = ownerRepository.getByName("владелец");
      System.out.println("Приюты: \n" + ownerDB.get(0).getName);
      System.out.println(ownerDB.get(1).getName);

      //Другой код
      for (Owner ownerItem : ownerRepository.findAll()){
        System.out.println("Владелец:" + ownerItem.getName());
        System.out.println("Приюты:");

        for (Shelter shelterItem : shelterRepository.findAll()){
          System.out.println("Название: " + shelterItem.getName());
        }

      }


    }
  • спасибо, я не совсем понимаю, как с этим работать в контроллере? как создать список Влдальцев с их приютами? – Tanya Apr 28 '20 at 14:33
  • @Tanya добавил. Я не успел расписать – Antonio112009 Apr 28 '20 at 14:35
  • у меня по сути есть только таблицы, сущности и репозитории, и имя владельца я заранее не знаю, в цикле нужно проходиться( сначала List owns = rep.findAll())? – Tanya Apr 28 '20 at 14:41
  • @Tanya не понятно, что вы хотите сделать. Не понятна суть вопроса – Antonio112009 Apr 28 '20 at 14:46
  • нужно вывести на список владельцев и их приюты, как именно мне нужно передать в шаблонизатор, и каким образом? – Tanya Apr 28 '20 at 14:52
  • в таком случае - findAll по владельцам, а после for-loop по owner.getShelters() – Antonio112009 Apr 28 '20 at 15:04
  • @Tanya обновил свой код (конец ответа смотреть) – Antonio112009 Apr 28 '20 at 15:10
  • @Tanya разобрались? – Antonio112009 Apr 28 '20 at 16:11
  • если использовать вложеннный фор, который Вы предложили, выводится сначала Владелец - а затем все приюты, а не приюты, который принадлежат владельцу( – Tanya Apr 28 '20 at 16:24