我正在尝试使用Criteria APi实现等效的内联sql。
select distinct t1
from tbl_ticket t1
left join tbl_tickets_updates t2 on t1.ticketnr = t2.ticketnr
where (t1.description ilike '%teste%' or t1.summary ilike '%teste%' or t2.description ilike '%teste%');
我的日志产生的结果
FINE:SELECT DISTINCT t0.ticketnr,t0.activity,t0.closereason, t0.contact,t0.contactfrom,t0.contactphone,t0.description, t0.enddate,t0.farea,t0.priority,t0.product,t0.release, t0.repgroup,t0.solution,t0.startdate,t0.status,t0.summary, t0.closer,t0.originator,t0.researcher FROM supportdb.public.tbl_ticket t0,supportdb.public.tbl_tickets_updates t2,supportdb.public.tbl_ticket t1 WHERE(((LOWER(t0.description)LIKE ?或更低(t0.summary)喜欢?)或更低(t1.description)喜欢?)和 (t1.ticketnr = t2.ticketnr))ORDER BY t0.startdate DESC
至于我的代码:
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Tickets> query = builder.createQuery(Tickets.class);
EntityType<Tickets> type = em.getMetamodel().entity(Tickets.class);
Root<Tickets> root = query.from(Tickets.class);
List<Predicate> predicatesAnd = new ArrayList<Predicate>();
query.distinct(true);
Subquery<TicketsUpdates> subquery = query.subquery(TicketsUpdates.class);
Root<TicketsUpdates> rootTicketsUpdates = subquery.from(TicketsUpdates.class);
Join<Tickets, TicketsUpdates> tupdates = rootTicketsUpdates.join("tickets");
//subquery.select(rootTicketsUpdates);
EntityType<TicketsUpdates> typeTU = em.getMetamodel().entity(TicketsUpdates.class);
predicatesAnd.add(builder.or(
builder.like(
builder.lower(
root.get(
type.getDeclaredSingularAttribute("description", String.class))), "%" + text.toLowerCase() + "%"),
builder.like(
builder.lower(
root.get(
type.getDeclaredSingularAttribute("summary", String.class))), "%" + text.toLowerCase() + "%"),
builder.like(
builder.lower(
tupdates.get(
typeTU.getDeclaredSingularAttribute("description", String.class))), "%" + text.toLowerCase() + "%")));
query.orderBy(builder.desc(root.get("startdate")));
我开始相信我做了一些令人难以置信的错误,尽管它应该很容易被发现,我想我可能会遗漏一些非常基本的东西。 这更像是对这个问题的跟进:JPA2, LEFT JOIN, Criteria API当时我没有注意到生成的sql代码不正确并且有5k记录但有400k记录......不完全正确。 :)
任何提示都非常受欢迎。 :)
编辑1 我的Tickets.class关系定义:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "tickets")
private Collection<TicketsUpdates> ticketsUpdatesCollection;
我的TicketsUpdates.class关系定义:
@JoinColumn(name = "ticketnr", referencedColumnName = "ticketnr", insertable = false, updatable = false)
@ManyToOne(optional = false)
private Tickets tickets;
并将代码更新为:
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Tickets> query = builder.createQuery(Tickets.class).distinct(true);
EntityType<Tickets> type = em.getMetamodel().entity(Tickets.class);
Root<TicketsUpdates> root = query.from(TicketsUpdates.class);
EntityType<TicketsUpdates> typeTU = em.getMetamodel().entity(TicketsUpdates.class);
Join<Tickets, TicketsUpdates> rootTickets = root.join("tickets");
List<Predicate> predicatesAnd = new ArrayList<Predicate>();
String test = "%test%";
Predicate p1 = builder.like(builder.lower(rootTickets.get("description").as(String.class)),test);
Predicate p2 = builder.like(builder.lower(rootTickets.get("summary").as(String.class)), test);
Predicate p3 = builder.like(builder.lower(root.get(typeTU.getDeclaredSingularAttribute("description", String.class))),test);
Predicate p4 = builder.or(p1, p2);
Predicate p5 = builder.or(p4, p3);
predicatesAnd.add(p5);
query.where(p5);
return em.createQuery(query).getResultList();