Как исправить правильное добавление в Set Hibernate Entity - PullRequest
0 голосов
/ 04 марта 2019

Я прочитал статью о правильном переопределении equals / hashCode: https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/

Эти переопределения выполняются, чтобы не потерять записи, уже записанные в Сет.

Код:

@Entity
public class Client {

    @Id
    @Column
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String name;

    public Client() {
    }

    public Client(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Client client = (Client) o;
        return Objects.equals(id, client.id) &&
                Objects.equals(name, client.name);
    }

    public int hashCode() {
        return 31;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Client{");
        sb.append("id=").append(id);
        sb.append(", name='").append(name).append('\'');
        sb.append('}');
        return sb.toString();
    }
}

Затем я проверяю свой класс, чтобы убедиться, что он работает правильно:

@Transactional
public class ClientTest {

    @PersistenceContext
    protected EntityManager em;

    @Test
    public void storeToSetBeforeMerge_ShouldBeContains() {
        Set<Client> map = new HashSet<>();
        Client client1 = new Client("John");
        Client client2 = new Client("Mike");
        map.add(client1);
        map.add(client2);

        Client merge1 = em.merge(client1);
        Client merge2 = em.merge(client2);

        assertTrue(map.contains(merge1));   // not true!
        assertTrue(map.contains(merge2));   // not true!
    }
}

Мой вопрос - почему условия не выполняются.В конце концов, я указал, что hashCode возвращает то же значение: 31. Что я делаю не так?

Я не могу понять смысл этого решения.Если это решение не решает проблему, я не могу найти нужный мне элемент из набора

Ответы [ 2 ]

0 голосов
/ 04 марта 2019

Вы не звонили persist() до merge(), как это сделано в статье.Автор статьи объясняет это в первом комментарии.

Слияние предназначено для интеграции изменений в отдельных объектах, которые были сохранены ранее.

Жизненный цикл нового объекта начинается с persist().Затем merge() вызывается на отдельном объекте с идентификатором, условие будет выполнено.

0 голосов
/ 04 марта 2019

Это потому, что HashSet не только сравнивает результаты hashCode.Он выполняет следующее:

  1. Он сравнивает результаты hashCode и, если результаты отличаются, возвращает значение true.
  2. Если результаты hashCode совпадаютзатем сравнивает объекты с помощью equals и возвращает результат.

Это из-за производительности - вычисление hashCode выполняется быстрее, и для hashCode рекомендуется не создавать коллизии очень часто.

Редактировать

В вашем методе equals вы сравниваете, используя id, что неверно, поскольку идентификатор генерируется базой данных:

public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Client client = (Client) o;
    return Objects.equals(id, client.id) && // <- comparison by id
            Objects.equals(name, client.name);
}

В вашем тестевы создаете объекты без идентификатора и помещаете их в HashSet, затем генерируете идентификатор и снова проверяете Collection:

@Test
public void storeToSetBeforeMerge_ShouldBeContains() {
    Set<Client> map = new HashSet<>();
    Client client1 = new Client("John");
    Client client2 = new Client("Mike");
    map.add(client1); // <- those don't have an id
    map.add(client2);

    Client merge1 = em.merge(client1); // those do have an id
    Client merge2 = em.merge(client2);

    assertTrue(map.contains(merge1));   // whose with id are not in set
    assertTrue(map.contains(merge2));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...