【问题标题】:Join on JPQL, CreateQuery加入 JPQL,CreateQuery
【发布时间】:2018-03-13 09:19:13
【问题描述】:

试图弄清楚 JPQL CreateQuery 上的连接是如何工作的。我有一个带有 SQL 代码的经理姓名的部分搜索功能:

SELECT
e.EMPLOYEE_ID      AS empId,
e.FIRST_NAME       AS empFirstName,
e.LAST_NAME        AS empLastName,
m.FIRST_NAME || ' ' || m.LAST_NAME AS empMgrName
FROM
EMPLOYEES e
LEFT JOIN
EMPLOYEES m ON e.MANAGER_ID = m.EMPLOYEE_ID
WHERE
LOWER(m.FIRST_NAME || ' ' || m.LAST_NAME) LIKE '%"ManagerName"%'

我尝试将其转换为 JPQL 格式,结果如下:

StringBuilder query = new StringBuilder();
query.setLength(0);
query.append(" FROM ");
query.append("    Employee e  ");
query.append(" JOIN ");
query.append("    e.Manager m  ");
query.append(" WHERE 1 = 1 ");
query.append("    LOWER(m.FIRST_NAME || ' ' || m.LAST_NAME) LIKE :empMgrName ");
Query listEmpQuery = JPA.em().createQuery(query.toString(), Employee.class);
if (!StringUtil.isNullOrEmpty(strMgr)) {
  listEmpQuery.setParameter("empMgrName", "%" + strMgr.toLowerCase() + "%");
}
List<Employee> listEmp = listEmpQuery.getResultList();

假设用户在strMgr 中输入了“ill gat”的值,以搜索经理名称“Bill Gates”。它应该搜索经理账单门下的员工。但是在这段代码中发生了ff错误:

IllegalArgumentException: Cannot create TypedQuery for query with more than one return using requested result type [models.db.Employee]] 

我做错了什么?

参考: Employee.class

@Entity
@Table(name="EMPLOYEES")
@SequenceGenerator(name = "EMPLOYEES_SEQ", sequenceName = "EMPLOYEES_SEQ")
public class Employee {

@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "EMPLOYEES_SEQ")
public Integer EMPLOYEE_ID;

public String FIRST_NAME;

public String LAST_NAME;

@OneToOne
@JoinColumn(name="MANAGER_ID")
public Employee Manager;

我以“经理”的身份将经理加入到员工中

【问题讨论】:

  • 不妨看看 Java 命名约定,尤其是属性名称。看看变量部分:oracle.com/technetwork/java/codeconventions-135099.html
  • JPQL 以“SELECT {alias}”开头,任何 JPQL 文档都会告诉你。 “||”是无效的 JPQL,但是有一个 CONCAT 函数。这个文档也会告诉你

标签: java hibernate jpa playframework jpql


【解决方案1】:

问题是,当查询中有多个实体时,您必须指定要作为结果的实体(除非它是投影)。

query.append(" SELECT e")
query.append(" FROM ");
query.append("    Employee e  ");
query.append(" JOIN ");
query.append("    e.Manager m  ");

或SELECT m,如果你想得到经理作为结果。

LIKE 子句很好。它是为防止 sql 注入而构建的。

【讨论】:

  • 您将其从外部联接更改为内部联接。而且我认为让 FETCH JOINS 获取连接以避免多对一关系中的数据重复是一种很好的做法。
【解决方案2】:

您想要实现的是 LEFT OUTER FETCH JOIN:

query.append("SELECT e FROM ");
query.append("    Employee e  ");
query.append("LEFT JOIN FETCH ");
query.append("    e.Manager");
query.append(" WHERE LOWER(CONCAT(m.FIRST_NAME, ' ', m.LAST_NAME)) LIKE :empMgrName ");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-17
    • 1970-01-01
    • 2014-02-04
    • 1970-01-01
    • 2017-06-20
    • 2011-09-17
    • 1970-01-01
    • 2011-04-13
    相关资源
    最近更新 更多