Почему hashcode () заставляет мое сопоставление JPA извлекать дочерние объекты даже при LAZY-загрузке и какова будет правильная реализация? - PullRequest
0 голосов
/ 30 апреля 2019

У меня есть две сущности Country и State

@Getter @Setter //@EqualsAndHashCode(doNotUseGetters=true)
@Entity
@Table(name = "country", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }) })
public class Country {

    @Id
    @Column(name = "country_id")
    private int countryId;

    @Column(name = "name", length = 45)
    private String name;

    @Column(name = "phonecode", length = 45)
    private int phoneCode;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "country")
    private Set<State> states;

}

@Getter @Setter // @EqualsAndHashCode(doNotUseGetters=true)
@Entity
@Table(name = "state")
public class State {

    @Id
    @Column(name = "state_id")
    private int stateId;

    @Column(name = "name", length = 45)
    @NotBlank
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "country_id", nullable = false)
    private Country country;

}

Я использую Spring-boot, поэтому я написал тест, чтобы получить города страны

    @Autowired
    private CountryDao countryDao;

    @Test
    @Transactional
    public void getAllStateWithCountryName() {
        Country country = countryDao.findById(101).orElseThrow(() -> new EntityNotFoundException());
        System.out.println("country: " + country.getName());
        country.getStates().forEach((state) -> {
            System.out.println("state: " + state.getName());            
        });
    }

В тот момент, когда я раскомментирую @EqualsAndHashCode(doNotUseGetters=true), отображение ведет себя EAGER и даже переходит к StackOverFlowError.Ранее я догадывался, что где-то в equals() или hashcode() вызывается getStates() (выглядит как загрузка EAGER), но так как я использовал флаг doNotUseGetters=true, который убедил меня, что геттер не находится впроблема.Затем я посмотрел на сгенерированный код lambok, и виновником был не получатель, а использование коллекции cities внутри реализации hashcode().

Сгенерированный hashCode()

public int hashCode()
  {
    int PRIME = 59;
    int result = 1;
    result = result * 59 + this.stateId;
    Object $name = this.name;
    result = result * 59 + ($name == null ? 43 : $name.hashCode());
    Object $cities = this.cities;
    result = result * 59 + ($cities == null ? 43 : $cities.hashCode()); //problem here

    return result;
  }

Проблема заключается в $cities.hashCode().Если я закомментирую это использование $cities, все будет нормально.

Итак, я должен реализовать свою собственную (не используя Lombok) реализацию hashCode(), сохраняя cities?Это будет правильная реализация?

Журналы:

Hibernate: select country0_.country_id as country_1_12_0_, country0_.name as name2_12_0_, country0_.phonecode as phonecod3_12_0_ from country country0_ where country0_.country_id=?
country: India
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
Hibernate: select states0_.country_id as country_3_38_0_, states0_.state_id as state_id1_38_0_, states0_.state_id as state_id1_38_1_, states0_.country_id as country_3_38_1_, states0_.name as name2_38_1_ from state states0_ where states0_.country_id=?
......................until stackoverlow error

1 Ответ

1 голос
/ 30 апреля 2019

Вы все еще можете использовать Lombok и исключить лениво извлеченную коллекцию из сгенерированного метода hashcode, вам просто нужно добавить аннотацию @EqualsAndHashCode.Exclude к вашей коллекции, как показано ниже.

@EqualsAndHashCode.Exclude
private Set<State> states;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...