@ManyToMany remove relation in Spring

@ManyToMany remove relation in Spring
AP
  • Rejestracja:około 6 lat
  • Ostatnio:prawie 4 lata
  • Postów:37
0
Kopiuj
    @Override
    public void deleteGroupById(Group group, User user) {
        user.getGroupSet().remove(group);
    }

relacje w encjach

Kopiuj
@ManyToMany(mappedBy = "group_list")
    private Set<User> userList = new HashSet<>();
Kopiuj
@ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(
            name = "user_group",
            joinColumns = { @JoinColumn(name = "user_id") },
            inverseJoinColumns = { @JoinColumn(name = "group_id") }
    )
    private Set<Group> group_list = new HashSet<>();

User przechowuje listę grup i na odwrót, grupa przechowuje listę userów. Stworzona jest trzecia tabela która przechowuje klucze obce do id_usera i id_grupy. Potrzebuję usuwać grupę o określonym id z listy dla konkretnego użytkownika o określonym id.

mam sobie taki kod, ale usuwa mi tylko object z seta, a relacja w bazie zostaje, jak to uczynić w Springu czy tam Hibernate żeby to śmigało? :)

edytowany 2x, ostatnio: AfrykanskiPomorSwin
K5
  • Rejestracja:około 6 lat
  • Ostatnio:dzień
  • Postów:1002
1
  1. W relacjach many to many nie używaj Cascade.All ani Cascade.Remove, do poczytania: https://thoughts-on-java.org/avoid-cascadetype-delete-many-assocations/
  2. Zamień to na cascade = {CascadeType.PERSIST, CascadeType.MERGE})
  3. Musisz zdecydować kto jest ownerem relacji (definiuje to mappedBy) i zmian dokonywać tylko po tej stronie:

The mappedBy attribute of the posts association in the Tag entity marks that, in this bidirectional relationship, the Post entity owns the association. This is needed since only one side can own a relationship, and > changes are only propagated to the database from this particular side.

W twoim wypadku User jest właścicielem relacji. Więc mając usera pobierasz zbiór gróp i usuwasz z niego grupę o twoim id.
Dodatkowo musisz z omawianej grupy, dostać się do zbioru userów i usunąć tego konkretnego.

AP
  • Rejestracja:około 6 lat
  • Ostatnio:prawie 4 lata
  • Postów:37
0

a pokażesz kod jak usuwać taką grupę?
trzeba mieć entityManagera czy jest jakaś magiczna sztuczka z metodami dostępnymi w crudRepository?

K5
  • Rejestracja:około 6 lat
  • Ostatnio:dzień
  • Postów:1002
0

EntityManager to raczje do usuwania grupy całkowicie z bazy :)
Ty chcesz tylko usunąć relacje. Więc w swojej metodzie usuwającej dodaj kolejna linijkę, coś ala:

Kopiuj
 group.getUserList().remove(user)
edytowany 1x, ostatnio: kixe52
Zobacz pozostałe 3 komentarze
K5
A przeczytałeś dwie ostatnie linie posta, który właśnie komentujemy?
AP
aaaa, że na odwrót :P
K5
"dodaj kolejną linijkę" - słowo klucz: KOLEJNĄ
AP
user.getGroupList().remove(group); group.getUserList().remove(user); nic się nie zmienia :P
K5
Wrzuć więcej kodu. Encje i klasy w których dokonujesz usuwania.
AP
  • Rejestracja:około 6 lat
  • Ostatnio:prawie 4 lata
  • Postów:37
0

Alternatywą byłoby zrobienie kolejnej encji UserGroup.java
z polami
private long id;
private long user_id;
private long group_id;

i zrobić

Kopiuj
public interface UserGroupRepository extends CrudRepository<UserGroup, Long> {
}
...
public interface UserGroupService {
  deleteRelation(long userId, long groupId);
}

...
    @Override
    public void deleteRelation(long userId, long groupId) {
        Set<UserGroup> userGroupSet = new HashSet<>();
        userGroupRepository.findAll().iterator().forEachRemaining(userGroupSet::add);
        for(UserGroup ug : userGroupSet)
            if(uq.getUserId()==userId && uq.getGroupId() == groupId)
               userGroupRepository.deleteById(uq.getId());
        userGroupRepository.deleteById(id);
    }

no ale brzydko to wygląda

edytowany 1x, ostatnio: AfrykanskiPomorSwin
AP
  • Rejestracja:około 6 lat
  • Ostatnio:prawie 4 lata
  • Postów:37
0

A więc tak, encja Group

Kopiuj
//imports ...
@Entity
public class Group {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    @Column(columnDefinition="DATETIME")
    @Temporal(TemporalType.TIMESTAMP)
    private Date lolA
    @Column(columnDefinition="DATETIME")
    @Temporal(TemporalType.TIMESTAMP)
    private Date lolB
    private int lolC

    @ManyToMany(mappedBy = "group_list")
    private Set<User> userList = new HashSet<>();

   //geters and setters ...
}

encja User

Kopiuj
//imports

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String name;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date birth_date;

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinTable(
            name = "group_user",
            joinColumns = { @JoinColumn(name = "user_id") },
            inverseJoinColumns = { @JoinColumn(name = "group_id") }
    )
    private Set<Group> groupList = new HashSet<>();

//geters and setters
}

userReporitory i groupRepository

Kopiuj
public interface UserRepository extends CrudRepository<User, Long> {
}
...

public interface GroupRepository extends CrudRepository<Group, Long> {
}

UserService

Kopiuj
public interface UserService {
    Set<User> getAll();
    User findById(Long id);
    void deleteById(Long id);
    void update(User t);
    void deleteGroupById(User user, Group group);
}

UserServiceImplementation

Kopiuj

@Service
public class UserServiceImpl implements UserService {
    private final UserRepository userRepository;

    public UserServiceImpl(UserRepository userRepository){
        this.userRepository = userRepository;
    }

    @Override
    public Set<User> getAll() {
        Set<User> userSet = new HashSet<>();
        userRepository.findAll().iterator().forEachRemaining(userSet::add);
        return userSet;
    }

    //findById wyciąłem tą metodę bo działa dobrze

    @Override
    public void deleteById(Long id) {
        userRepository.deleteById(id);
    }

    @Override
    public void update(User t) {
        userRepository.save(t);
    }

    @Override
    public void deleteGroupById(User user, Group group) {
        user.getGroupList().remove(group);
        group.getUserList().remove(user);
    }
}

edytowany 1x, ostatnio: AfrykanskiPomorSwin
K5
Equals + hashCode ?
AP
że niby przesłonić te metody?
AP
lol, po co, nie porównuję obiektów ;p
K5
  • Rejestracja:około 6 lat
  • Ostatnio:dzień
  • Postów:1002
3
AfrykanskiPomorSwin napisał(a):

lol, po co, nie porównuję obiektów ;p

Niech mi ktoś jeszcze raz powie, że zaczęcie pisania webówki bez ogarnięcia podstaw javy jest spoko pomysłem, bo przecież da się to ogarnąć podczas projektu webowego :)

Wykorzystujesz w swoim kodzie HashSet. Skąd java ma wiedzieć, że obiekt, który chcesz usunąć znajduje się w zbiorze?

Polecam poczytać o kontrakcie equals - hashode oraz o tym jak działa HashSet / HashMapa w Javie.

edytowany 1x, ostatnio: kixe52
Zobacz pozostałe 26 komentarzy
K5
Zawsze możesz iść na bootcamp :)
AP
@Service @Transactional, działa :D dwóch klientów odpala w tym samym czasie /user/1/group/delete/1 i nie ma błędów :) sprawdzane przy użyciu klasy Robot :P
WE
wow, jestem pod wrażeniem nieświadomości swoich braków i ogromnego ego przy takich umiejętnościach i wiedzy, nie życzę nikomu takiej osoby w zespole
AP
powiedziała osoba mająca 10 punktów :D

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.