JPA:使用 criteriabuilder 查找实体:属性名称与注释不同?

JPA: Using criteriabuilder to find entities: Attribute name different from annotation?

我有一个包含员工信息的 mysql 数据库,每个员工都有一个技术 ID 作为主键。在 MySQL 中选择行匹配条件,我可以使用以下语句(有效)

SELECT * FROM database_test.employee WHERE fist_name='First1';

在 Java 中,我还可以将其用作本机语句来获得我想要的(有效):

        List<EmployeeEntity2> objects = m_em.createNativeQuery(
            "SELECT * database_test.employee WHERE first_name='First1'",
            EmployeeEntity2.class).getResultList();

但是,我想使用 Criteriabuilder 获得相同的结果,然后将其概括为多个 columnName=columnEntry 选择。

public List<EmployeeEntity2> testNoParameter() {

    //Based on https://www.objectdb.com/java/jpa/query/criteria

    CriteriaBuilder cb = m_em.getCriteriaBuilder();

    CriteriaQuery<EmployeeEntity2> q = cb.createQuery(EmployeeEntity2.class);
    Root<EmployeeEntity2> c = q.from(EmployeeEntity2.class);
    ParameterExpression<String> p = cb.parameter(String.class);
    //Works
    //q.select(c).where(cb.equal(c.get("firstName"), p));
    //Won't work
    q.select(c).where(cb.equal(c.get("first_name"), p));        
    TypedQuery<EmployeeEntity2> query = m_em.createQuery(q);

    query.setParameter(p, "First1");
    List<EmployeeEntity2> results = query.getResultList();
    return results;
}

使用 "fist_name" - 实体中的列名注释 - 将产生以下 java.lang.IllegalArgumentException 其中:

    Unable to locate Attribute  with the the given name [first_name] on this ManagedType [xx.xxx.database.EmployeeEntity2]

EmployeeEntity2 有 "fist_name" 注释:

@Column(name = "first_name", nullable = false)
@Override
public String getFirstName() {
    return super.getFirstName();
}

所以 "first_name" 应该存在,但是(通过一些调试)我发现预期的属性是出于某种原因 "firstName" 而不是 - 我没有 defined/annotated - 所以在哪里它来自 - 我如何使用数据库中实际定义的列名(列 = "first_name")?

您应该使用 属性 实体名称(而不是列名称)在条件生成器中使用它,而不是

 q.select(c).where(cb.equal(c.get("first_name"), p));  

使用

 q.select(c).where(cb.equal(c.get("firstName"), p));  

CriteriaBuilder 与 RDBMS 模式无关,因此您使用模型(实体),而不是模式(table 名称等)。

在 JPA 中,您通常不使用 SQL,而是使用 JPQL。在 JPQL 中你的 SQL 相当于

"SELECT e FROM EmployeEntity2 e WHERE e.firstName='First1'"

CriteriaQuery 树和 JPQL 字符串稍后会向下转换为相同的查询树(不记得名字了),因此它们都必须遵守相同的规则。