#java #criteria #hibernate-criteria #criteria-api
#java #критерии #переход в спящий режим-критерии #критерии-api
Вопрос:
Моя проблема в том, что когда я устанавливаю cb.или он делает cb и .. cb является CriteriaBuilder, мой класс :
public class User extends BaseEntity<User> {
public static final String CHILDREN_FIELD = "children";
public static final String PARENT_FIELD = "parent";
//Id column based in BaseEntity
OneToOne(fetch = LAZY)
JoinColumn(name = "parent_partner_id")
User parent;
OneToMany(mappedBy = "parent", fetch = LAZY,cascade = {})
private List<User> children;
Мой критерий кода :
Root<User> root = query.from(User.class);
Join<User, User> userJoin = root.join(CHILDREN_FIELD, JoinType.LEFT);
userJoin.on(
cb.or(
cb.equal(userJoin.get(ID_FIELD), root.get("id")))
);
Код генерирует :
select
user0_.id as col_0_0_
from
user user0_
left outer join
user children2_
on user0_.id=children2_.parent_id
and ( <- i write OR in cb!! why it generates AND ?
children2_.id=user0_.id
)
Как я могу это решить? Почему мой код генерирует оператор AND?
Комментарии:
1. Привет, имеет ли смысл этот запрос с точки зрения SQL? Я этого не понимаю.
2. Я использую postgesql
Ответ №1:
Вероятно, это потому, что у вас есть один аргумент в вашем вызове метода or
cb.or(cb.equal(userJoin.get(ID_FIELD), root.get("id"))));
должно быть
cb.or(arg1, arg2); // arg1 OR arg2
Ответ №2:
Мне жаль говорить вам, что с критериями API сегодня это невозможно, я расскажу вам о разных вариантах:
1.- Использовать собственный запрос
Использование собственного запроса не является проблемой, поскольку вы используете предложения, поддерживаемые всеми менеджерами БД
List<User> result = em.createNativeQuery("select * from user p "
"left outer join user p1 on p.id = p1.parent_id or p.id = p1.id",
"User.nativeConstructorMapping").getResultList();
В вашей сущности
@SqlResultSetMappings({
@SqlResultSetMapping(name="User.nativeConstructorMapping",
classes = {
@ConstructorResult(
targetClass = Users.class,
columns = {
@ColumnResult(name = "id", type = Long.class),
@ColumnResult(name = "name", type = String.class)
[...]
})
})
})
....
public User(Long id, String name, [...]) {
super();
this.id= id;
this.name = name
[...]
}
2.- Используйте два корня, на случай, если вместо left join вам подойдет inner join, добавив условия предложения on в where
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> root1 = query.from(User.class);
Root<User> root2 = query.from(User.class);
query.where(cb.or(
cb.equal(root1.get(User_.id),root2.get(User_.parent).get(User_.id)),
cb.equal(root1.get(User_.id),root2.get(User_.id)))
);
Как я вам говорил, хотя не рекомендуется использовать собственные запросы, потому что это противоречит философии JPA, в этом случае, поскольку вы не используете предложения какой-либо базы данных, это не должно быть проблемой, я бы выбрал тот вариант, который я бы выбрал.