title: Merging 3 tables and searching by the last
body: <p>I have a Property entity that has the id for a City entity.
  The City entity that has the id for a State entity.
  And the State entity that has the id for a Country entity.</p>
  
  <p>I need to find all propreties in a country.</p>
  
  <p>My solution is this one: </p>
  
  <pre><code>protected Specification&lt;Property&gt; createSpecification(PropertyCriteria criteria) {
      ...
      if (criteria.getCountryId() != null) {
              StateCriteria stateCriteria = new StateCriteria();
              stateCriteria.setCountryId(criteria.getCountryId());
              List&lt;StateDTO&gt; states = stateQueryService.findByCriteria(stateCriteria);
              List&lt;Long&gt; statesIds = states.stream().map(StateDTO::getId).collect(Collectors.toList());
  
              LongFilter statesInCountry = new LongFilter();
              statesInCountry.setIn(statesIds);
  
              CityCriteria cityCriteria = new CityCriteria();
              cityCriteria.setStateId(statesInCountry);
              List&lt;CityDTO&gt; cities = cityQueryService.findByCriteria(cityCriteria);
              List&lt;Long&gt; citiesId = cities.stream().map(CityDTO::getId).collect(Collectors.toList());
  
              LongFilter citiesInState = new LongFilter();
              citiesInState.setIn(citiesId);
  
              specification = specification.and(buildSpecification(citiesInState,
                  root -&gt; root.join(Property_.city, JoinType.LEFT).get(City_.id)));
      }
      ...
  }
  </code></pre>
  
  <p>Is there a better solution using <code>buildSpecification()</code>? I find really difficult to understand what the inhered functions from <code>QueryService</code> actually do because of the type parametrization.</p>
  
  <p>Thanks in advance!</p>