У меня есть сущность:
public class Foo {
@Id
@GeneratedValue
private Long id;
private String username;
@ManyToOne(cascade = { CascadeType.MERGE }, fetch = FetchType.LAZY, optional = true)
@JoinColumn(name = "ParentID", nullable = true)
private Foo parent;
// other fields
}
При таком типе отношений каждый объект Foo имеет родителя, кроме первого экземпляра Foo в БД, который имеет NULL ParentID. Когда я пытаюсь создать запрос через критерии API и пытаюсь найти первый объект Foo (нулевой родительский идентификатор), используя любое из его свойств (идентификатор, имя пользователя и т. Д.), Я получаю:
javax.persistence.NoResultException: No entity found for query
Как должен быть реализован JoinColumn в этом случае? Как мне получить первый объект Foo в БД с нулевым родительским идентификатором?
Спасибо
Обновлено 28 сентября 2011 года
Чего я пытаюсь добиться, так это искать все Foos с именем пользователя, начинающимся с «foo», и хотел бы использовать его в качестве отдельного возвращаемого объекта:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder;
CriteriaQuery<FooDto> criteriaQuery = criteriaBuilder.createQuery(FooDto.class);
Root<Foo> foo = criteriaQuery.from(Foo.class);
criteriaQuery.multiselect(foo.get("id"), foo.get("username"), foo.get("parent").get("username"), foo.get("property1")
//other selected properties);
Predicate predicate = criteriaBuilder.conjunction();
predicate = criteriaBuilder.and(predicate, criteriaBuilder.like(foo.get("username").as(String.class), criteriaBuilder.parameter(String.class, "username")));
// other criteria
criteriaQuery.where(predicate);
TypedQuery<FooDto> typedQuery = entityManager.createQuery(criteriaQuery);
typedQuery.setParameter("username", "foo%");
// other parameters
// return result
при условии, что имена пользователей - это foo1, foo2 и foo3, где foo1 имеет нулевого родителя, результирующий набор будет возвращать только foo2 и foo3, даже если foo1 имеет имя пользователя, которое начинается с указанного предиката.
а также поиск только одного foo1 выдаст
javax.persistence.NoResultException: No entity found for query
Есть ли способ добавить foo1 к остальным результатам? или foo1 всегда будет особым случаем, так как я должен добавить критерий, указывающий, что родительский элемент является нулевым? Или, возможно, я пропустил опцию в joinColumn, чтобы сделать это.
Спасибо
ОБНОВЛЕНО Чт 29 сентября 13:03:41 PHT 2011
@mikku
Я обновил часть критериев поста выше (property1), потому что я думаю, что именно эта часть отвечает за то, что foo1 не будет включена в Result Set.
Вот частичное представление сгенерированного запроса из журналов:
select
foo.id as id,
foo.username as username,
foo.password as password,
foo.ParentID as parentId,
foo_.username as parentUsername,
foo.SiteID as siteId,
from FOO_table foo, FOO_table foo_ cross join Sites site2_
where foo.ParentID=foo_.id and foo.SiteID=site2_.id and 1=1
and foo.username=? and site2_.remoteKey=? limit ?
и это не будет возвращать Foo1, очевидно, потому что значение имени пользователя взято из foo_, поэтому мой первый вопрос «как мне добраться до Foo1».
В той части, которую я прокомментировал, что я плохо использую SelectCase и смешаю ее с вашим первым ответом, я добавил эту часть на множественный выбор:
criteriaBuilder
.selectCase()
.when(criteriaBuilder.isNotNull(agent.get("parent")), agent.get("parent").get("username"))
.otherwise(criteriaBuilder.literal("")),
замена
foo.get("parent").get("username")
Однако это также не позволит получить Foo1. Мое последнее прибежище, хотя и неэффективное, вероятно, проверит, имеют ли параметры значение Foo1, и создаст критерийQuery, задающий буквальное значение для имени пользователя и использующий запрос по умолчанию в противном случае.
Предложения / альтернативы очень ценятся.