我刚刚意识到当任何参数为null时,JPQL where子句不能像我预期的那样工作.例如,这个简单的JPQL查询
SELECT en FROM Entity en WHERE en.name = :name
Run Code Online (Sandbox Code Playgroud)
当name参数为null时,即使数据库中存在名称设置为null的实体,也不会返回任何结果.
在那种情况下,Hibernate用SQL执行WHERE entity.NAME = null.显然,这不是由数据库处理的,因为标准定义IS NULL了空比较(参见SQL为null和= null).JPQL也有IS NULL运算符(http://docs.oracle.com/javaee/6/tutorial/doc/bnbuf.html#bnbvi),其行为与SQL完全相同(http://docs.oracle.com/javaee/6 /tutorial/doc/bnbuf.html#bnbvr).
我认为这是一个常见的情况,但快速搜索没有给我任何有趣的结果.
那么,有没有办法在查询中包含空值?到目前为止,我想出了以下内容:
SELECT en FROM Entity en WHERE (:name IS NULL AND en.name IS NULL) OR en.name = :name
Run Code Online (Sandbox Code Playgroud)
它工作正常,但看起来不优雅,尤其是在较大的查询中.
奖金问题:为什么JPQL模仿SQL这个奇怪的方面?
在我的应用程序中有一个实体:
@Entity
@Table(schema = "hr", name = "personal_data")
public class PersonalData {
}
Run Code Online (Sandbox Code Playgroud)
和Spring的application.properties中定义的连接字符串:
spring.datasource.url=jdbc:mysql://localhost/mobile?UseUnicode=true&characterEncoding=utf8
Run Code Online (Sandbox Code Playgroud)
如果我调用以下代码:
TypedQuery<E> typedQuery = em.createQuery("from PersonalData pd where pd.employeeId = ?1", PersonalData.class);
typedQuery.setParameter(1, 123);
return typedQuery.getSingleResult();
Run Code Online (Sandbox Code Playgroud)
它会导致这个SQL:
select * from personal_data personalda0_ where personalda0_.employee_id=?
Run Code Online (Sandbox Code Playgroud)
哪个会因例外而失败
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'mobile.personal_data' doesn't exist
Run Code Online (Sandbox Code Playgroud)
因为该表personal_data是在hr数据库中定义的,并且没有这样的表mobile.
这在Hibernate 4.3.13中运行正常(即SQL中的表名以数据库名称为前缀),并在应用程序迁移到使用Hibernate 5.2.14的Spring Boot 2.0时停止.有没有办法在Hibernate 5.x中实现旧的行为?