JPA 命名查询是 JPA 提供的一种查询方式,它可以让我们在实体类中定义一个静态的查询,这样就可以在其他地方直接使用这个查询。
JPA 命名查询有两种形式:NamedQuery 和 NamedNativeQuery。NamedQuery 是使用 JPQL 语句来定义的,而 NamedNativeQuery 是使用原生 SQL 语句来定义的。
@Entity @Table(name = "user") @NamedQueries({ @NamedQuery(name = "User.findByName", query = "SELECT u FROM User u WHERE u.name = :name"), @NamedQuery(name = "User.findByAge", query = "SELECT u FROM User u WHERE u.age = :age") }) public class User { // 省略其他代码... }
上面的代码中,我们使用 @NamedQueries 注解来定义了两个命名查询,分别是根据 name 和 age 条件查询 User 的信息。
我们可以通过 EntityManager 的 createNamedQuery() 方法来获取这两个命名查询:
TypedQuery<User> query1 = entityManager.createNamedQuery("User.findByName", User.class); TypedQuery<User> query2 = entityManager.createNamedQuery("User.findByAge", User.class);
然后我们就可以对这些 Query 进行设置参数和执行操作了:
query1.setParameter("name", "John"); List<User> users1 = query1.getResultList(); query2.setParameter("age", 20); List<User> users2 = query2.getResultList();
JPA 命名查询有很多优势,例如能够将 SQL 语句和 Java 类分离开来、能够重复使用相同的 SQL 语句、能够减少字符串字面量带来的问题、能够减少代码量、能够易于理解和修改等。因此 JPA 命名查询是一种很好的方式来实现数据库访问。
在命名查询中,我们还可以添加参数。
@Entity @NamedQueries({ @NamedQuery(name="findEmployeesAboveSal", query="SELECT e " + "FROM Employee e " + "WHERE e.department = :dept AND " + " e.salary > :sal"), @NamedQuery(name="findHighestPaidByDepartment", query="SELECT e " + "FROM Employee e " + "WHERE e.department = :dept AND " + " e.salary = (SELECT MAX(e2.salary) " + " FROM Employee e2 " + " WHERE e2.department = :dept)") }) public class Employee {
以下代码来自Employee.java。
package cn..common; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.Temporal; import javax.persistence.TemporalType; @Entity @NamedQueries({ @NamedQuery(name="findEmployeesAboveSal", query="SELECT e " + "FROM Employee e " + "WHERE e.department = :dept AND " + " e.salary > :sal"), @NamedQuery(name="findHighestPaidByDepartment", query="SELECT e " + "FROM Employee e " + "WHERE e.department = :dept AND " + " e.salary = (SELECT MAX(e2.salary) " + " FROM Employee e2 " + " WHERE e2.department = :dept)") }) public class Employee { @Id private int id; private String name; private long salary; @Temporal(TemporalType.DATE) private Date startDate; @ManyToOne private Employee manager; @OneToMany(mappedBy="manager") private Collection<Employee> directs; @ManyToOne private Department department; @ManyToMany private Collection<Project> projects; public Employee() { projects = new ArrayList<Project>(); directs = new ArrayList<Employee>(); } public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } public void setSalary(long salary) { this.salary = salary; } public void setStartDate(Date startDate) { this.startDate = startDate; } public void setManager(Employee manager) { this.manager = manager; } public void setDirects(Collection<Employee> directs) { this.directs = directs; } public void setDepartment(Department department) { this.department = department; } public void setProjects(Collection<Project> projects) { this.projects = projects; } public int getId() { return id; } public String getName() { return name; } public long getSalary() { return salary; } public Date getStartDate() { return startDate; } public Department getDepartment() { return department; } public Collection<Employee> getDirects() { return directs; } public Employee getManager() { return manager; } public Collection<Project> getProjects() { return projects; } public String toString() { return "Employee " + getId() + ": name: " + getName() + ", salary: " + getSalary() + ", dept: " + ((getDepartment() == null) ? null : getDepartment().getName()); } }
以下代码来自Project.java。
package cn..common; import java.util.ArrayList; import java.util.Collection; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.ManyToMany; @Entity public class Project { @Id protected int id; protected String name; @ManyToMany(mappedBy="projects") private Collection<Employee> employees; public Project() { employees = new ArrayList<Employee>(); } public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } public void setEmployees(Collection<Employee> employees) { this.employees = employees; } public int getId() { return id; } public String getName() { return name; } public Collection<Employee> getEmployees() { return employees; } public String toString() { return "Project id: " + getId() + ", name: " + getName(); } }
下面的代码来自Department.java。
package cn..common; import java.util.ArrayList; import java.util.Collection; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.OneToMany; @Entity public class Department { @Id private int id; private String name; @OneToMany(mappedBy="department") private Collection<Employee> employees; public Department() { employees = new ArrayList<Employee>(); } public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } public void setEmployees(Collection<Employee> employees) { this.employees = employees; } public int getId() { return id; } public String getName() { return name; } public Collection<Employee> getEmployees() { return employees; } public String toString() { return "Department no: " + getId() + ", name: " + getName(); } }
下面的代码来自PersonDaoImpl.java。
package cn..common; import java.util.Collection; import java.util.Date; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.PersistenceContext; import javax.persistence.TemporalType; import org.springframework.transaction.annotation.Transactional; @Transactional public class PersonDaoImpl { public void test() { Employee emp = new Employee(); emp.setName("Tom"); emp.setSalary(123); emp.setStartDate(new Date()); emp.setId(1); Project pro = new Project(); pro.setName("Design"); pro.getEmployees().add(emp); Department dept = new Department(); dept.setName("Dept"); dept.getEmployees().add(emp); emp.setDepartment(dept); emp.getProjects().add(pro); em.persist(dept); em.persist(pro); em.persist(emp); String deptName = "Dept"; String empName = "Tom"; } public Collection<Employee> findEmployeesHiredDuringPeriod(Date start, Date end) { return (Collection<Employee>) em.createQuery("SELECT e " + "FROM Employee e " + "WHERE e.startDate BETWEEN :start AND :end") .setParameter("start", start, TemporalType.DATE) .setParameter("end", end, TemporalType.DATE) .getResultList(); } public Employee findHighestPaidByDepartment(Department dept) { try { return (Employee) em.createNamedQuery("findHighestPaidByDepartment") .setParameter("dept", dept) .getSingleResult(); } catch (NoResultException e) { return null; } } public Collection<Employee> findAllEmployees() { return (Collection<Employee>) em.createQuery( "SELECT e FROM Employee e").getResultList(); } @PersistenceContext private EntityManager em; }下载 Named_Query_ParamTypes.zip
以下是数据库转储。
Table Name: DEPARTMENT Row: Column Name: ID, Column Type: INTEGER: Column Value: 0 Column Name: NAME, Column Type: VARCHAR: Column Value: Dept Table Name: EMPLOYEE Row: Column Name: ID, Column Type: INTEGER: Column Value: 1 Column Name: NAME, Column Type: VARCHAR: Column Value: Tom Column Name: SALARY, Column Type: BIGINT: Column Value: 123 Column Name: STARTDATE, Column Type: DATE: Column Value: 2014-12-29 Column Name: DEPARTMENT_ID, Column Type: INTEGER: Column Value: 0 Column Name: MANAGER_ID, Column Type: INTEGER: Column Value: null Table Name: EMPLOYEE_PROJECT Row: Column Name: EMPLOYEES_ID, Column Type: INTEGER: Column Value: 1 Column Name: PROJECTS_ID, Column Type: INTEGER: Column Value: 0 Table Name: PROJECT Row: Column Name: ID, Column Type: INTEGER: Column Value: 0 Column Name: NAME, Column Type: VARCHAR: Column Value: Design
JPA教程 -JPA查询简介示例最简单的JPQL查询选择单个实体类型的所有实例。考虑下面的查询:SELECT eFROM Employee eJPQL尽可能使用...
JPA教程 -JPA 查询计数其中子查询示例以下代码显示如何在子查询中使用COUNT函数。List l = em.createQuery(SELECT m FROM Profes...
JPA教程 - JPA 查询Exists示例如果子查询返回任何行,则EXISTS条件返回true。以下代码显示如何在JPQL中使用带有子查询的EXISTS运...
JPA教程 -JPA查询日期参数示例我们可以在查询中使用日期类型值。以下代码使用EntityManager创建具有两个参数的查询。然后它传递...
JPA教程 -JPA查询All示例我们可以在JPQL中使用带有子查询的ALL运算符。List l = em.createQuery( SELECT e FROM Professor e WHE...