@ManyToMany remove relation in Spring

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

relacje w encjach

@ManyToMany(mappedBy = "group_list")
    private Set<User> userList = new HashSet<>();
@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? :)

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.

0

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

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:

 group.getUserList().remove(user)
0

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

i zrobić

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

0

A więc tak, encja Group

//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

//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

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

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

UserService

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


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

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.

1 użytkowników online, w tym zalogowanych: 0, gości: 1