У меня есть классы Account и Role, сопоставленные «многие ко многим», тестовый класс и класс контроллера. Когда я запускаю тест, все в порядке, но в контроллере тот же код не работает (точнее, первый вызов контроллера удаляет только сопоставление в таблице учетных записей в postgres, и только второй вызов контроллера удаляет все учетные записи). Так почему же один и тот же код по-разному действует в тесте и в контроллере? Есть ли какой-либо скрытый контроль транзакций? Здесь или в Google нет вопросов с такой же проблемой: (* 1001 *
Ниже объектов, тест и контроллер.
Класс учетной записи
package github.aaa4.server.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
@Entity
@Data
@NoArgsConstructor
public class Account extends PersistenceUnit {
private String name;
private String email;
private String encodedPassword;
public Account(String name) {
this.name = name;
}
public Account(String name, String email) {
this.name = name;
this.email = email;
}
@ToString.Exclude
@EqualsAndHashCode.Exclude
@ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
@JoinTable(name = "account_role",
joinColumns = {@JoinColumn(name = "account_id")},
inverseJoinColumns = {@JoinColumn(name = "role_id")})
Set<Role> roles = new HashSet<>();
@EqualsAndHashCode.Exclude
@ToString.Exclude
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "account")
Set<VerificationToken> tokens = new HashSet<>();
public void addNewRole(Role role) {
if (roles == null) {
roles = new HashSet<>();
}
roles.add(role);
role.getAccounts().add(this);
}
public void removeRole(Role role) {
roles.remove(role);
role.getAccounts().remove(this);
}
public void addNewToken(VerificationToken token) {
if (tokens == null)
tokens = new HashSet<>();
tokens.add(token);
token.setAccount(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Account)) return false;
if (!super.equals(o)) return false;
Account account = (Account) o;
return Objects.equals(name, account.name) &&
Objects.equals(email, account.email);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), name, email);
}
}
Роль. Класс
package github.aaa4.server.entity;
import lombok.*;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ManyToMany;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
@Entity
@Data
@NoArgsConstructor
@RequiredArgsConstructor
public class Role extends PersistenceUnit {
@NonNull
private Roles role;
@ToString.Exclude
@EqualsAndHashCode.Exclude
@ManyToMany(mappedBy = "roles", fetch = FetchType.EAGER,
cascade = {CascadeType.MERGE, CascadeType.PERSIST})
private Set<Account> accounts = new HashSet<>();
public void addNewAccount(Account account){
if (accounts == null){
accounts = new HashSet<>();
}
accounts.add(account);
account.getRoles().add(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Role)) return false;
if (!super.equals(o)) return false;
Role role1 = (Role) o;
return role == role1.role;
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), role);
}
@Override
public String toString() {
return "Role{" +
"role=" + role +
", accounts=" + accounts +
'}';
}
}
SQL для таблицы
create table if not exists account (
id uuid not null primary key,
name varchar(30),
email varchar(50),
encoded_password varchar(50),
created_at timestamp,
updated_at timestamp
);
create table if not exists role (
id uuid not null primary key,
role integer,
created_at timestamp,
updated_at timestamp
);
create table if not exists account_role (
account_id uuid,
role_id uuid,
constraint fk_account_id
foreign key (account_id)
references account (id),
constraint fk_role_id
foreign key (role_id)
references role (id)
);
Класс испытаний
package github.aaa4.server.newTests;
import github.aaa4.server.entity.Account;
import github.aaa4.server.entity.Role;
import github.aaa4.server.entity.Roles;
import github.aaa4.server.repo.AccountRepository;
import github.aaa4.server.repo.RoleRepository;
import github.aaa4.server.services.AccountAndRoleService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.assertEquals;
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestDeletion {
@Autowired
RoleRepository roleRepository;
@Autowired
AccountAndRoleService service;
@Autowired
AccountRepository accountRepository;
Account editorsAccount = new Account("Ikki");
Role editor = new Role(Roles.EDITOR);
@Test
public void deleteAllTest(){
roleRepository.save(editor);
service.saveAccount(editorsAccount);
editorsAccount.addNewRole(editor);
service.saveAccount(editorsAccount);
assertEquals(editorsAccount, accountRepository.findDistinctByName(editorsAccount.getName()).get());
service.findAll().forEach(account -> service.deleteAccount(account));
assertEquals(0,accountRepository.findAll().size());
}
}
Класс контроллера
package github.aaa4.server.web.controllers.web;
import github.aaa4.server.entity.Account;
import github.aaa4.server.entity.Role;
import github.aaa4.server.entity.Roles;
import github.aaa4.server.repo.AccountRepository;
import github.aaa4.server.services.AccountAndRoleService;
import github.aaa4.server.web.controllers.web.DTO.AccountDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponentsBuilder;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@Slf4j
@CrossOrigin(origins = "http://localhost:4200")
@RestController
@RequestMapping("/users")
class RegistrationController {
@Autowired
AccountAndRoleService service;
@Autowired
AccountRepository accountRepository;
@GetMapping("/devclear")
public String deleteAll() {
service.findAll().forEach(account -> service.deleteAccount(account));
return "done!";
}
}
Класс обслуживания
package github.aaa4.server.services;
import github.aaa4.server.entity.Account;
import github.aaa4.server.entity.Role;
import github.aaa4.server.entity.Roles;
import github.aaa4.server.entity.VerificationToken;
import github.aaa4.server.repo.AccountRepository;
import github.aaa4.server.repo.RoleRepository;
import github.aaa4.server.repo.VerificationTokenRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Service
@Slf4j
public class AccountAndRoleService {
public void deleteAccount(Account account){
account.setRoles(new HashSet<>());
accountRepository.save(account);
accountRepository.delete(account);
}
}
Спасибо, что прочитали этот вопрос :).