JPQL 命名查询

通常情况下,我们都是直接将 JPQL 查询语句写到 createNamedQuery("JPQL 语句") 方法中,例如:

EntityManager em = factory.createEntityManager();
Query query = em.createQuery("select t from User t where t.id=?1");
query.setParameter(1, 1);

JPQL 命名查询指将上面示例中的 JPQL 通过 @NamedQuery 注解配置在实体类或映射的超类上。给该 JPQL 指定一个唯一名称,然后通过 createNamedQuery("JPQL 命名名称") 方法进行调用。

以下是 JPQL 中命名查询的定义示例:

@NamedQuery(
    name="findAllCustomersWithName",
    query="SELECT c FROM Customer c WHERE c.name LIKE :custName"
)

上面定义了一个名为 findAllCustomersWithName 的 JPQL 查询语句。以下是使用命名查询的示例:

@PersistenceContext
public EntityManager em;
...
customers = em.createNamedQuery("findAllCustomersWithName")
        .setParameter("custName", "Smith")
        .getResultList();

示例代码

本示例还是以用户和用户的图书为例,演示 JPQL 命名查询的用法。详细步骤如下:

(1)配置 persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
    <persistence-unit name="openJPA" transaction-type="RESOURCE_LOCAL">
        <!-- JPA提供者 -->
        <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
        <!-- 声明实体类 -->
        <class>com.hxstrive.openjpa.entity.User</class>
        <class>com.hxstrive.openjpa.entity.Book</class>
        <!-- 配置JPA数据库属性 -->
        <properties>
            <property name="openjpa.ConnectionURL"
                      value="jdbc:mysql://localhost:3306/openjpa_learn?useSSL=false&amp;
                      serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
            <property name="openjpa.ConnectionDriverName" value="com.mysql.jdbc.Driver"/>
            <property name="openjpa.ConnectionUserName" value="root"/>
            <property name="openjpa.ConnectionPassword" value="aaaaaa"/>
            <property name="openjpa.Log" value="SQL=TRACE"/>
            <!-- 自动生成表 -->
            <property name="openjpa.jdbc.SynchronizeMappings"
                      value="buildSchema(ForeignKeys=true)"/>
            <!-- 不使用加载时强化和编译时强化,使用运行时Unenhanced(不能发挥OpenJPA的最大效能,所以也不推荐) -->
            <property name="openjpa.ClassLoadEnhancement" value="false"/>
            <property name="openjpa.DynamicEnhancementAgent" value="false"/>
            <property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
        </properties>
    </persistence-unit>
</persistence>

(2)用户表实体映射,其中使用 @OneToMany 指定一对多映射,一个用户拥有多本图书。代码如下:

@Data
@Entity
@Table
@NamedQueries({
    @NamedQuery(name = "find_users", query = "Select u from User u"),
    @NamedQuery(name = "find_byId", query = "Select u from User u where u.id=:id")
})
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column
    private String name;

    @Column
    private Integer age;

    @Column
    private Float salary;

    @OneToMany(cascade = CascadeType.ALL)
    private List<Book> bookList;
}

上面代码中,通过 @NamedQueries 或者 @NamedQuery 注解定义了两个命名 JPQL 查询。

(3)图书表实体映射,代码如下:

@Data
@Entity
@Table
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column
    private String name;

    @Column
    private float price;
}

(4)客户端代码

import com.hxstrive.openjpa.entity.User;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import java.util.List;

public class JPQLDemo2 {
    /** 持久化单元名称 */
    private static final String PERSISTENCE_NAME = "openJPA";

    public static void main(String[] args) {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory(
                PERSISTENCE_NAME, System.getProperties());
        EntityManager em = factory.createEntityManager();

        Query query = em.createNamedQuery("find_byId");
        query.setParameter("id", 1);
        List<User> userList = query.getResultList();
        for (User user : userList) {
            System.out.println(user);
        }

        em.close();
        factory.close();
        System.out.println("finished.");
    }

}

运行客户端输出的 SQL 日志如下:

SELECT t0.id, t0.age, t0.name, t0.salary FROM User t0 WHERE (t0.id = ?) [params=?]
SELECT t1.id, t1.name, t1.price FROM User_Book t0 INNER JOIN Book t1 ON t0.BOOKLIST_ID = t1.id WHERE t0.USER_ID = ? [params=?]
User{id=1, name='用户-0', age=56, salary=7251.132, bookList=[{"id":1,"name":"图书-用户-0-0","price":40.912487},{"id":2,"name":"图书-用户-0-1","price":25.45687},{"id":3,"name":"图书-用户-0-2","price":87.681984},{"id":4,"name":"图书-用户-0-3","price":94.50937}]}
finished.
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号