Выберите объект из объединенной таблицы с помощью JPA Criteria-API - PullRequest
4 голосов
/ 17 февраля 2012

Я борюсь около двух дней со следующей проблемой и надеюсь, что вы можете дать мне толчок в правильном направлении. Обучающие материалы и примеры, которые я нашел во время своего исследования, всегда показывали, как легко работать в критериях API. Прежде всего, у меня есть два класса:

@Entity
public class Offer {

  private String name;
  @ManyToOne private Location location;
  private String tags;
}

и

@Entity
public class Location {
  private String name;
  private string tags;
}

Поскольку мне нужно избегать циклических ссылок, связь между этими классами является только однонаправленной. В этих классах много дополнительных атрибутов, и я хочу создавать динамические запросы в зависимости от моего поискового фильтра. Следующий оператор SQL должен объяснить, что мне нравится делать:

SELECT l 
FROM Offer o 
JOIN o.location l
WHERE o.tags LIKE :sometag AND l.tags LIKE :someothertag

После реализации с критериями API я получил этот код:

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Location> criteriaQuery = criteriaBuilder.createQuery(Location.class);
criteriaQuery = criteriaQuery.distinct(true);
Join location;
ArrayList<Predicate> whereList = new ArrayList<Predicate>();

// if filter by offer, use offer as main table and join location table
if (filter.getOfferTags() != null) {
  Root<Offer> offer = criteriaQuery.from(Offer.class);

  location = offer.join("location");


  // limit to offering tags
  Path<String> tagPath = offer.get("tags");

  for (String tag : filter.getOfferTags()) {
    Predicate whereTag = criteriaBuilder.like(tagPath, "%" + tag + "%");
    whereList.add(whereTag);
  }

} else {
  // else use location table as base
  location = (Join<Location, Location>) criteriaQuery.from(Location.class);
}

Но если я выполню это, я получу следующее сообщение об ошибке из моей базы данных H2:

Column "LOCATION.ID" not found; SQL statement: 
SELECT DISTINCT LOCATION.ID, LOCATION.NAME
FROM OFFER t0, LOCATION t1 
WHERE t0.TAGS LIKE ? AND t1.TAGS LIKE ?

База данных ожидает t1.ID и t1.NAME в предложении select, а не LOCATION.ID и LOCATION.NAME. Как я могу сказать JPA создать «правильный» запрос? Я что-то упустил в своем коде?

Я использую Glassfish 3.1.1 с Eclipse Link и базой данных H2.

Ответы [ 2 ]

6 голосов
/ 17 февраля 2012

Я думаю, вы просто пропустили выбор в вашем запросе:

criteriaQuery.select(location);
4 голосов
/ 17 февраля 2012

Я не думаю, что вам нужно явно указывать соединение в запросе - ведь предложение уже имеет привязку к местоположению.

Что-то вроде этого будет достаточно:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Location> cq = criteriaBuilder.createQuery(Location.class);
Root<Offer> offer = criteriaQuery.from(Offer.class);
cq.select(offer.get("location"));
cq.where(... )
...