首页 > 编程笔记 > Java笔记 阅读:16

JPA命名查询语句的定义和调用(附带实例)

除了使用 @Query 注解外,还可以使用 @NamedQuery 与 @NameQueries 等注解定义命名查询。

JPA 的命名查询实际上就是给 SQL 查询语句起一个名字,执行查询时就是直接使用起的名字,避免重复写 JPQL 语句,使得查询方法能够复用。

JPA定义命名查询

在实体类中,@NamedQuery 注解定义一个命名查询语句,示例代码如下:
@Entity
@Table(name="t_user")
@NamedQuery(name="findAllUser",query="SELECT u FROM User u")
public class User {
    // Entity实体类相关定义
}
在上面的示例中,@NamedQuery 中的 name 属性指定命名查询的名称,query 属性指定命名查询的语句。

如果要定义多个命名查询方法,则需要使用 @NamedQueries 注解:
@Entity
@Table(name="users")
@NamedQueries({
    @NamedQuery(name="findAllUser",query="SELECT u FROM User u"),
    @NamedQuery(name="findUserWithId",query="SELECT u FROM User u WHERE u.id = ?1"),
    @NamedQuery(name="findUserWithName",query="SELECT u FROM User u WHERE u.name = :name")
})
public class User {
    // Entity实体类相关定义
}
在上面的示例中,在 User 实体类中定义了 findAllUser()、findUserWithId()、findUserWithName() 三种方法。

JPA调用命名查询

定义命名查询后,可以使用 EntityManager 类中的 createNamedQuery() 方法传入命名查询的名称来创建查询:
@Resource
EntityManagerFactory emf;

@Test
public void testNamedQuery() {
    EntityManager em = emf.createEntityManager();
    Query query =  em.createNamedQuery("findUserWithName");// 根据User实体中定义的命名查询
    query.setParameter("name", "weiz");
    List<User> users = query.getResultList();
    for (User u : users){
        System.out.println("name:"+u.getName()+",age:"+u.getAge());
    }
}
在上面的示例中,使用 createNamedQuery 创建对应的查询,JPA 会先根据传入的查询名查找对应的 NamedQuery,然后通过调用 getResultList() 方法执行查询并返回结果。

运行验证

单击 Run Test 或在方法上右击,选择 Run 'testNamedQuery',运行全部测试方法,结果如下图所示:


图 1 已命名查询的运行结果

定义的已命名查询 findUserWithName 的单元测试运行成功,并输出了相应的查询结果,说明使用 JPA 实现了自定义的已命名查询的功能。

除了使用 @NamedQuery 注解的方式之外,Spring Data JPA 提供的 Named 查询可以支持将 SQL 语句写至 XML 文件中,实现 SQL 与 Java 代码的分离。

在 resources/META-INF 目录下创建 orm.xml 文件并定义命名方法,参考配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings version="2.0" xmlns="http://java.sun.com/xml/ns/persistence/orm"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm
                 http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/persistence/orm_2_2.xsd ">
    <named-native-query name="findUserWithName2" result-class="com.weiz.example01.model.User">
        <description>通过name查询用户数据</description>
        <query>select u.id , u.name , u.password , u.age from users u where u.name = :name</query>
    </named-native-query>
</entity-mappings>
在 orm.xml 文件中使用 <named-native-query> 标签定义 queryByName 的命名查询,使用 XML 的方式与使用 @NamedQuery 注解方式的效果是一样的。只是将 SQL 语句写至 XML 文件中,实现 SQL 与 Java 代码的分离,使得定义的 Java 实体类看起来不那么复杂、臃肿。

相关文章