EclipseLink JPA CriteriaQuery 正在创建错误的 SQL 查询
EclipseLink JPA CriteriaQuery is creating an erroneous SQL query
我正在尝试使用 LazyDataModel 为任何实体在 Primefaces 数据表中实现通用过滤系统,但在尝试搜索涉及一对多关系的字段时给我带来了问题,因为它会生成错误的 SQL 查询,我的代码如下我将跳过一些不相关的部分以使其尽可能简单:
实体是 Client 和 Fault:
@Entity
@Table(name = "ges_fault")
public class Fault extends Item implements Serializable, ItemIf{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "client_id", nullable = true)
private Client client;
// Getters and setters
客户class:
@Entity
@Table(name="ges_client")
public class Client extends Item implements Serializable, ItemIf {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
@OneToMany(cascade = CascadeType.ALL,mappedBy="client", fetch = FetchType.LAZY)
private List<Fault> faults;
// Getters and setters
为了抽象问题,最终条件查询如下所示:
CriteriaBuilder qb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Fault> c = qb.createQuery(Fault.class);
Root<Fault> root = c.from(Fault.class);
c.select(root);
List<Predicate> predicates = new ArrayList<Predicate>();
Expression<String> exp = root.get("client");
predicates.add(qb.like(exp,"%" + 1 + "%"));
c.where(predicates.toArray(new Predicate[]{}));
List<Fault>result = q.getResultList();
return result;
我得到的错误是:
Internal Exception:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an
error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near 'LIKE '%1%' AND
(t0.ID = t1.client_id)) LIMIT 0, 12' at line 1
错误代码:1064 调用:
SELECT t1.ID AS a1, t1.NOMBRE AS a8, t1.client_id AS a9 FROM
ges_client t0, ges_fault t1 WHERE ( LIKE ? AND (t0.ID =
t1.client_id)) LIMIT ?, ? bind => [3 parameters bound] Query:
ReadAllQuery(referenceClass=Falta sql="SELECT t1.ID AS a1, t1.NOMBRE
AS a8, t1.client_id AS a9 FROM ges_client t0, ges_falta t1 WHERE (
LIKE ? AND (t0.ID = t1.client_id)) LIMIT ?, ?") at
org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340)
at
org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:682)
at
org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
at
org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2002)
at
org.eclipse.persistence.sessions.server.ServerSession.executeCall(ServerSession.java:570)
at
org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
因为我正在尝试做的事情我不能使用这种查询:
Expression<String> exp = root.get(Fault_.client);
所以这不是一个可行的解决方案。
希望有人能帮帮我。
您可能想要过滤客户的 name
属性。在这种情况下,请使用以下语法之一,具体取决于您是否使用类型安全的 MetaModel:
Path<Client> client = root.get(Fault_.client);
Path<String> exp = client.get(Client_.name);
或:
Path<Client> client = root.get("client");
Path<String> exp = client.get("name");
在这两种情况下,您都可以避免在 Path 中指定 class,或者您甚至可以完全避免显式实例化客户端变量:
Path exp = root.get(Fault_.client).get(Client_.name);
或
Path client = root.get(Fault_.client);
Path exp = client.get(Client_.name);
都是合法的,以及使用属性名称 "client"
和 "name"
而不是元模型的等效项。
然后,按照创建 Predicate
表达式的方式继续操作。
我正在尝试使用 LazyDataModel 为任何实体在 Primefaces 数据表中实现通用过滤系统,但在尝试搜索涉及一对多关系的字段时给我带来了问题,因为它会生成错误的 SQL 查询,我的代码如下我将跳过一些不相关的部分以使其尽可能简单:
实体是 Client 和 Fault:
@Entity
@Table(name = "ges_fault")
public class Fault extends Item implements Serializable, ItemIf{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "client_id", nullable = true)
private Client client;
// Getters and setters
客户class:
@Entity
@Table(name="ges_client")
public class Client extends Item implements Serializable, ItemIf {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
@OneToMany(cascade = CascadeType.ALL,mappedBy="client", fetch = FetchType.LAZY)
private List<Fault> faults;
// Getters and setters
为了抽象问题,最终条件查询如下所示:
CriteriaBuilder qb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Fault> c = qb.createQuery(Fault.class);
Root<Fault> root = c.from(Fault.class);
c.select(root);
List<Predicate> predicates = new ArrayList<Predicate>();
Expression<String> exp = root.get("client");
predicates.add(qb.like(exp,"%" + 1 + "%"));
c.where(predicates.toArray(new Predicate[]{}));
List<Fault>result = q.getResultList();
return result;
我得到的错误是:
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LIKE '%1%' AND (t0.ID = t1.client_id)) LIMIT 0, 12' at line 1
错误代码:1064 调用:
SELECT t1.ID AS a1, t1.NOMBRE AS a8, t1.client_id AS a9 FROM ges_client t0, ges_fault t1 WHERE ( LIKE ? AND (t0.ID = t1.client_id)) LIMIT ?, ? bind => [3 parameters bound] Query: ReadAllQuery(referenceClass=Falta sql="SELECT t1.ID AS a1, t1.NOMBRE AS a8, t1.client_id AS a9 FROM ges_client t0, ges_falta t1 WHERE ( LIKE ? AND (t0.ID = t1.client_id)) LIMIT ?, ?") at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:682) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558) at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2002) at org.eclipse.persistence.sessions.server.ServerSession.executeCall(ServerSession.java:570) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
因为我正在尝试做的事情我不能使用这种查询:
Expression<String> exp = root.get(Fault_.client);
所以这不是一个可行的解决方案。
希望有人能帮帮我。
您可能想要过滤客户的 name
属性。在这种情况下,请使用以下语法之一,具体取决于您是否使用类型安全的 MetaModel:
Path<Client> client = root.get(Fault_.client);
Path<String> exp = client.get(Client_.name);
或:
Path<Client> client = root.get("client");
Path<String> exp = client.get("name");
在这两种情况下,您都可以避免在 Path 中指定 class,或者您甚至可以完全避免显式实例化客户端变量:
Path exp = root.get(Fault_.client).get(Client_.name);
或
Path client = root.get(Fault_.client);
Path exp = client.get(Client_.name);
都是合法的,以及使用属性名称 "client"
和 "name"
而不是元模型的等效项。
然后,按照创建 Predicate
表达式的方式继续操作。