JPA, удаление объекта из Hashset сущности требует вызова геттера для сохранения работоспособности - PullRequest
0 голосов
/ 21 апреля 2019

Я пытаюсь persit изменения, которые я делаю в сущности , когда я пытаюсь удалить объект из Hashset .Я не понимаю, почему мои первые две версии не работают , а - третья.

В пятом тесте я обновляю сущность

В шестом тесте я пытаюсь проверить, действует ли обновление с предыдущего теста.Три версии методов удаления дают разные результаты для этого теста.Первые два не работают, а третий работает.

Настройка тестов

  @Inject
  private InvitationManagerBean invitationManagerBean;
  private Student host1;
  private Attendant guest;
  private int id;
  private Attendant guest2;
  private Attendant guest3;
  @PersistenceContext
  private EntityManager entityManager;

  @Deployment
  public static JavaArchive createDeployment() {
    return ShrinkWrap.create(JavaArchive.class)
      .addPackage(InvitationManagerBean.class.getPackage())
      .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")
      .addAsManifestResource(new ClassLoaderAsset("META-INF/persistence.xml"), "persistence.xml");
  }

  @Before
  public void initialize() {
    host1 = new Student("john", "wick", "johnwick@gmail.com");
    guest = new Attendant("tony", "iommi");
    guest2 = new Attendant("marge", "simpson");
    guest3 = new Attendant("homer", "simpson");
  }

Пятый тест, Этот тест работает с каждой версией метода удаления

@Test
@InSequence(5)
  public void removeTest() throws StudentDoesNotExistException, GuestDoesNotExistException {
    //query
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Student> criteria = builder.createQuery(Student.class);
    Root<Student> root = criteria.from(Student.class);
    criteria.select(root).where(builder.equal(root.get("mail"), host1.getMail()));
    TypedQuery<Student> query = entityManager.createQuery(criteria);
    Student res;
    res = query.getSingleResult();

    assertEquals(3, res.getGuests().size());
    assertTrue(res.hasInvited(guest));
    assertTrue(res.hasInvited(guest2));
    assertTrue(res.hasInvited(guest3));
    assertTrue(invitationManagerBean.remove(res, "homer", "simpson"));
    assertEquals(2, res.getGuests().size());
    assertTrue(res.hasInvited(guest));
    assertTrue(res.hasInvited(guest2));
    assertFalse(res.hasInvited(guest3));
  }

Шестой тест терпит неудачу с первыми двумя версиями метода "remove" .Сбой assertEquals, потому что имеет значение 3 вместо 2 , что означает, что операция удаления из пятого теста не работает

  @Test
  @InSequence(6)
  public void removeNotExistTest() throws StudentDoesNotExistException, GuestDoesNotExistException {

    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Student> criteria = builder.createQuery(Student.class);
    Root<Student> root = criteria.from(Student.class);
    criteria.select(root).where(builder.equal(root.get("mail"), host1.getMail()));
    TypedQuery<Student> query = entityManager.createQuery(criteria);
    Student res;
    res = query.getSingleResult();
    assertEquals(2, res.getGuests().size());           //IS 3 WHEN FAILS
  }

первая версия метода удаления и первый метод removeGuest (), на который он опирается .


public boolean remove(Student host, String name, String lastName) throws StudentDoesNotExistException, GuestDoesNotExistException{
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Student> criteria = builder.createQuery(Student.class);
    Root<Student> root = criteria.from(Student.class);
    criteria.select(root).where(builder.equal(root.get("mail"), host.getMail()));
    TypedQuery<Student> query = entityManager.createQuery(criteria);
    Student s;
    Attendant guest;
    guest = new Attendant(name, lastName);

    try {
      s = query.getSingleResult();


    } catch (NoResultException e) {
      throw new StudentDoesNotExistException("the host does no exist");
    } catch(Exception e){
      return false;
    }

    if(!s.hasInvited(guest)) {
      throw new GuestDoesNotExistException("tried to remove a guest that has not been invited");
    }
    s.removeGuest(guest);                 //CHANGE IS HERE


    return true;

  public void removeGuest(Attendant a) {
    guests.remove(a);
  }

вторая версия метода удаления опирается на вторую версию метода removeGuest в классе Student:

  public void removeGuest(Attendant a) {
    getGuests().remove(a);
  }

третья версия метода удаления ...

s.getGuests().removeIf(v -> v.getName().equals(name) && v.getLastName().equals(lastName));

... опирается на следующий метод removeGuest ():

  public void removeGuest(Attendant a) {
    guests.remove(a);
  }

Ученик класса

@Entity
@DiscriminatorValue(value = "S")
public class Student extends Attendant implements Serializable {


  @Pattern(regexp = "\\d{10}+", message = "Invalid creditCardNumber")
  private String creditCard;

  @OneToMany(cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST}, fetch = FetchType.LAZY)
  private Set<Attendant> guests;

  public Set<Attendant> getGuests() {
    return guests;
  }

  public Student() {
    super();

  }

  public Student(String name, String lastName, String mail) {
    super(name, lastName);
    this.mail = mail;
    guests = new HashSet<>();
  }

  public String getCreditCard() {
    return creditCard;
  }

  public void setCreditCard(String creditCard) {
    this.creditCard = creditCard;
  }


  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    if (!super.equals(o)) return false;
    Student student = (Student) o;
    return Objects.equals(mail, student.mail) && Objects.equals(creditCard, student.creditCard);
  }

  @Override
  public int hashCode() {
    return Objects.hash(super.hashCode(), creditCard, mail);
  }

  @Override
  public String toString() {
    return "Student{" +
      "creditCard='" + creditCard + '\'' +
      "} " + super.toString();
  }

  public void addGuest(Attendant a) {
    guests.add(a);

  }

  public void removeGuest(Attendant a) {
    guests.remove(a);
  }

  public boolean hasInvited(Attendant a) {
    return guests.contains(a);
  }

}

Оператор равно и хэш-код

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Attendant attendant = (Attendant) o;
        return name.equals(attendant.name) &&
                lastName.equals(attendant.lastName) ;
    }

  @Override
  public int hashCode() {
    return Objects.hash(name, lastName);
  }
...