我必须为以下 Oracle-SQL 编写一个 JPQL 查询:
SELECT * FROM Foo f, Bar b, Xyz x WHERE f.id = b.foo(+) and f.id = x.foo(+) and (lower(f.label) like lower('%filter%') or lower(f.code) like lower('%filter%') or lower(b.label) like lower('%filter%') or lower(x.label) like ('%filter%');
有多个 Bar 和 Xyz 表,每个 Bar/Xyz 对都连接到 Foo 的一个子类:
@Entity
@Table(name = "FOO")
// JOINED doesn't work because of an EclipseLink error!
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "TP", discriminatorType = DiscriminatorType.STRING, length = 5)
public abstract class Foo extends AbstractEntity {
private static final long serialVersionUID = -9137682737124302402L;
@Column(name = "CODE", nullable = false, length = 40)
private String code;
@Column(name = "LABEL", nullable = false, length = 4000)
private String label;
//...other properties
}
@Entity
@Table(name = "ABCD")
@DiscriminatorValue("ABCD")
public class Abcd extends Foo {
private static final long serialVersionUID = 250474360860393393L;
@OneToMany(mappedBy = "abcd")
@OrderColumn(name = "IDX")
private List<Bar> barList;
@OneToMany(mappedBy = "abcd")
@OrderColumn(name = "IDX")
private List<Xyz> xyzList;
protected Abcd() {
this.barList = new ArrayList<Bar>();
this.xyzList = new ArrayList<Xyz>();
}
//...getter/setter
}
@Entity
@Table(name = "BAR")
public class Bar extends AbstractEntity {
private static final long serialVersionUID = 2628239098357340769L;
@ManyToOne(fetch = FetchType.EAGER, optional = false, cascade = CascadeType.ALL)
@JoinColumns({ @JoinColumn(name = "ABCD_ID", referencedColumnName = "ID", nullable = false) })
private Abcd abcd;
@Column(name = "LABEL", nullable = false, length = 4000)
private String label;
protected Bar() {
}
// ...getter/setter, some other properties
}
@Entity
@Table(name = "XYZ")
public class Xyz extends AbstractEntity {
private static final long serialVersionUID = 2628239098357350769L;
@ManyToOne(fetch = FetchType.EAGER, optional = false, cascade = CascadeType.ALL)
@JoinColumns({ @JoinColumn(name = "ABCD_ID", referencedColumnName = "ID", nullable = false) })
private Abcd abcd;
@Column(name = "LABEL", nullable = false, length = 4000)
private String label;
protected Xyz() {
}
// ...getter/setter, some other properties
}
@MappedSuperclass
public abstract class AbstractEntity {
private static final long serialVersionUID = -8574667350713432415L;
@EmbeddedId
private PersistId id;
public static boolean isId(PersistId id) {
return (id != null && id.getId() > 0);
}
public boolean hasId() {
return isId(getId());
}
public PersistId getId() {
return this.id;
}
public void setId(PersistId id) {
this.id = id;
}
}
PersistId 封装了一个名为 ID 的列,目前实现为 Long。正如我之前所说,Foo 还有一些其他子类,它们连接到其他一些类,例如 Bar/Xyz。
如何在 Eclipselink 中实现 SQL(使用 Criteria API)?我已经测试了一些不同的东西,但我没有得到任何结果。我还使用子查询来获取与过滤器匹配的 ABCD_ID,但是我在匹配 Foo 和 Abcd 时遇到了问题。我有两种方法,分别生成查询和过滤器参数。
private CriteriaQuery<Foo> getQuery() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Foo> query = criteriaBuilder.createQuery(Foo.class);
Root<Foo> foo = query.from(Foo.class);
query.select(foo);
query.distinct(true);
return query;
}
private CriteriaQuery<Foo> addFilter(CriteriaQuery<Foo> query, String fullTextFilter) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
Set<Root<?>> roots = query.getRoots();
Iterator<Root<?>> iter = roots.iterator();
Root<Foo> foo = (Root<Foo>) iter.next();
List<Predicate> criteria = new ArrayList<Predicate>();
if (fullTextFilter != null) {
ParameterExpression<String> p = criteriaBuilder.parameter(String.class, "filter");
Path<String> label = foo.<String>get("label");
Path<String> code = foo.<String>get("code");
// TODO: add some code to handle Bar and Xyz labels
criteria.add(criteriaBuilder.or(criteriaBuilder.like(criteriaBuilder.lower(label), criteriaBuilder.lower(p)),
criteriaBuilder.like(criteriaBuilder.lower(code), criteriaBuilder.lower(p))));
}
if (criteria.size() == 1) {
query.where(criteria.get(0));
}
if (criteria.size() > 1) {
query.where(criteriaBuilder.and(criteria.toArray(new Predicate[0])));
}
return query;
}
有任何想法吗?我想,我还没有理解 Criteria API 的任何基本内容,你能用一些源代码启发我吗?
谢谢安德烈