我有一个包含员工信息的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”,而是我没有定义/注释的名称,因此它来自何处,以及如何我使用数据库中实际定义的列名(column =“ first_name”)?
答案 0 :(得分:1)
您应使用实体的属性名称(而非列名称)在条件构建器中使用它,而不是
q.select(c).where(cb.equal(c.get("first_name"), p));
使用
q.select(c).where(cb.equal(c.get("firstName"), p));
CriteriaBuilder
与RDBMS模式无关,因此您使用模型(实体),而不使用模式(表名称等)。
在JPA中,通常不使用SQL,而使用JPQL。在JPQL中,等效的SQL类似于
"SELECT e FROM EmployeEntity2 e WHERE e.firstName='First1'"
以后CriteriaQuery
树和JPQL
字符串都向下转换为同一查询树(不记得名称),因此它们都必须遵守完全相同的规则。