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> query = entityManager.createNamedQuery("User.findByName", User.class); query.setParameter("name", "John"); List<User> users = query.getResultList();
上面的代码中,我们通过 createNamedQuery() 方法来获取了一个 TypedQuery 实例,然后再设置 name 的值并执行 getResultList() 方法来获取所有匹配的 User 实体。
JPA 命名查询是一种很好的方式来实现数据库访问层和应用层之间的分离,因此在开发 JPA 应用时应尽量使用命名查询。
命名查询是用于组织查询定义和提高应用程序性能的强大工具。
命名查询是使用@NamedQuery注释定义的,它可以放在任何实体的类定义上。
注释定义查询的名称以及查询文本。
以下代码显示如何使用注释创建命名查询。
@NamedQuery(name="findSalaryForNameAndDepartment", query="SELECT e.salary " + "FROM Employee e " + "WHERE e.department.name = :deptName AND " + " e.name = :empName")
命名查询通常放置在最直接对应于查询结果的实体类上,因此Employee实体将是此命名查询的良好位置。
查询的名称的范围限定为整个持久性单元,并且在该范围内必须是唯一的。
通常的做法是在查询名称前加上实体名称。
例如,Employee实体的“findAll”查询将命名为“Employee.findAll”。
以下代码显示为实体创建多个命名查询
@NamedQueries({ @NamedQuery(name="Employee.findAll", query="SELECT e FROM Employee e"), @NamedQuery(name="Employee.findByPrimaryKey", query="SELECT e FROM Employee e WHERE e.id = :id"), @NamedQuery(name="Employee.findByName", query="SELECT e FROM Employee e WHERE e.name = :name") })
以下代码创建单个命名查询。
@Entity @NamedQuery(name="findSalary", query="SELECT e.salary " + "FROM Professor e ") public class Professor {
以下代码来自Phone.java。
package cn..common; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.ManyToOne; @Entity public class Phone { @Id private long id; private String number; private String type; @ManyToOne Professor employee; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getNumber() { return number; } public void setNumber(String phoneNo) { this.number = phoneNo; } public String getType() { return type; } public void setType(String phoneType) { this.type = phoneType; } public Professor getProfessor() { return employee; } public void setProfessor(Professor employee) { this.employee = employee; } public String toString() { return "Phone id: " + getId() + ", no: " + getNumber() + ", type: " + getType(); } }
以下代码来自App.java。
package cn..common; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml"); PersonDaoImpl dao = (PersonDaoImpl) context.getBean("personDao"); dao.test(); context.close(); Helper.checkData(); } }
以下代码来自Professor.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.JoinColumn; import javax.persistence.JoinColumns; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.Temporal; import javax.persistence.TemporalType; @Entity @NamedQuery(name="findSalary", query="SELECT e.salary " + "FROM Professor e ") public class Professor { @Id private int id; private String name; private long salary; @Temporal(TemporalType.DATE) private Date startDate; @OneToOne private Address address; @OneToMany(mappedBy="employee") private Collection<Phone> phones = new ArrayList<Phone>(); @ManyToOne private Department department; @ManyToOne private Professor manager; @OneToMany(mappedBy="manager") private Collection<Professor> directs = new ArrayList<Professor>(); @ManyToMany(mappedBy="employees") private Collection<Project> projects = new ArrayList<Project>(); public int getId() { return id; } public void setId(int empNo) { this.id = empNo; } public String getName() { return name; } public void setName(String name) { this.name = name; } public long getSalary() { return salary; } public void setSalary(long salary) { this.salary = salary; } public Date getStartDate() { return startDate; } public void setStartDate(Date startDate) { this.startDate = startDate; } public Collection<Phone> getPhones() { return phones; } public void addPhone(Phone phone) { if (!getPhones().contains(phone)) { getPhones().add(phone); if (phone.getProfessor() != null) { phone.getProfessor().getPhones().remove(phone); } phone.setProfessor(this); } } public Department getDepartment() { return department; } public void setDepartment(Department department) { if (this.department != null) { this.department.getProfessors().remove(this); } this.department = department; this.department.getProfessors().add(this); } public Collection<Professor> getDirects() { return directs; } public void addDirect(Professor employee) { if (!getDirects().contains(employee)) { getDirects().add(employee); if (employee.getManager() != null) { employee.getManager().getDirects().remove(employee); } employee.setManager(this); } } public Professor getManager() { return manager; } public void setManager(Professor manager) { this.manager = manager; } public Collection<Project> getProjects() { return projects; } public void addProject(Project project) { if (!getProjects().contains(project)) { getProjects().add(project); } if (!project.getProfessors().contains(this)) { project.getProfessors().add(this); } } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public String toString() { return "Professor " + getId() + ": name: " + getName() + ", salary: " + getSalary() + ", phones: " + getPhones() + ", managerNo: " + ((getManager() == null) ? null : getManager().getId()) + ", deptNo: " + ((getDepartment() == null) ? null : getDepartment().getId()); } }
以下代码来自Project.java。
package cn..common; import java.util.ArrayList; import java.util.Collection; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Inheritance; import javax.persistence.ManyToMany; @Entity @Inheritance public class Project { @Id protected int id; protected String name; @ManyToMany protected Collection<Professor> employees = new ArrayList<Professor>(); public int getId() { return id; } public void setId(int projectNo) { this.id = projectNo; } public String getName() { return name; } public void setName(String projectName) { this.name = projectName; } public Collection<Professor> getProfessors() { return employees; } public void addProfessor(Professor employee) { if (!getProfessors().contains(employee)) { getProfessors().add(employee); } if (!employee.getProjects().contains(this)) { employee.getProjects().add(this); } } public String toString() { return getClass().getName().substring(getClass().getName().lastIndexOf(".")+1) + " no: " + getId() + ", name: " + getName(); } }
以下代码来自Address.java。
package cn..common; import javax.persistence.Entity; import javax.persistence.Id; @Entity public class Address { @Id private int id; private String street; private String city; private String state; private String zip; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getStreet() { return street; } public void setStreet(String address) { this.street = address; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getState() { return state; } public void setState(String state) { this.state = state; } public String getZip() { return zip; } public void setZip(String zip) { this.zip = zip; } public String toString() { return "Address id: " + getId() + ", street: " + getStreet() + ", city: " + getCity() + ", state: " + getState() + ", zip: " + getZip(); } }
下面的代码来自Department.java。
package cn..common; import java.util.HashSet; import java.util.Set; 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 Set<Professor> employees = new HashSet<Professor>(); public int getId() { return id; } public void setId(int deptNo) { this.id = deptNo; } public String getName() { return name; } public void setName(String deptName) { this.name = deptName; } public Set<Professor> getProfessors() { return employees; } public String toString() { return "Department no: " + getId() + ", name: " + getName(); } }
下面的代码来自PersonDaoImpl.java。
package cn..common; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.springframework.transaction.annotation.Transactional; @Transactional public class PersonDaoImpl { public void test() { prepareData(); Object l = em.createNamedQuery("findSalary").getSingleResult(); printResult(l); } private void prepareData() { Address address = new Address(); address.setState("BC"); Professor p = new Professor(); p.setId(0); p.setName("TOM"); p.setSalary(1111L); p.setAddress(address); Department d = new Department(); d.setId(1); d.setName("Design"); p.setDepartment(d); d.getProfessors().add(p); Phone phone = new Phone(); phone.setId(1); phone.setNumber("111-111-1111"); phone.setProfessor(p); em.persist(p); em.persist(phone); em.persist(address); em.persist(d); } private static void printResult(Object result) { if (result == null) { System.out.print("NULL"); } else if (result instanceof Object[]) { Object[] row = (Object[]) result; System.out.print("["); for (int i = 0; i < row.length; i++) { printResult(row[i]); } System.out.print("]"); } else if (result instanceof Long || result instanceof Double || result instanceof String) { System.out.print(result.getClass().getName() + ": " + result); } else { System.out.print(result); } System.out.println(); } @PersistenceContext private EntityManager em; }下载 Query_Named.zip
上面的代码生成以下结果。
以下是数据库转储。
Table Name: ADDRESS Row: Column Name: ID, Column Type: INTEGER: Column Value: 0 Column Name: CITY, Column Type: VARCHAR: Column Value: null Column Name: STATE, Column Type: VARCHAR: Column Value: BC Column Name: STREET, Column Type: VARCHAR: Column Value: null Column Name: ZIP, Column Type: VARCHAR: Column Value: null Table Name: DEPARTMENT Row: Column Name: ID, Column Type: INTEGER: Column Value: 1 Column Name: NAME, Column Type: VARCHAR: Column Value: Design Table Name: PHONE Row: Column Name: ID, Column Type: BIGINT: Column Value: 1 Column Name: NUMBER, Column Type: VARCHAR: Column Value: 111-111-1111 Column Name: TYPE, Column Type: VARCHAR: Column Value: null Column Name: EMPLOYEE_ID, Column Type: INTEGER: Column Value: 0 Table Name: PROFESSOR Row: Column Name: ID, Column Type: INTEGER: Column Value: 0 Column Name: NAME, Column Type: VARCHAR: Column Value: TOM Column Name: SALARY, Column Type: BIGINT: Column Value: 1111 Column Name: STARTDATE, Column Type: DATE: Column Value: null Column Name: ADDRESS_ID, Column Type: INTEGER: Column Value: 0 Column Name: DEPARTMENT_ID, Column Type: INTEGER: Column Value: 1 Column Name: MANAGER_ID, Column Type: INTEGER: Column Value: null Table Name: PROJECT Table Name: PROJECT_PROFESSOR
JPA教程 - JPA查询Not Empty示例JPA SQL可以检查属性是否为空。List l = em.createQuery(SELECT p FROM Project p WHERE p.e...
Lucene教程 -Lucene HelloWorld我们可以使用Lucene为您的应用程序添加全文搜索功能。索引我们将从一些字符串创建一个内存索引。S...
Java反射 - Java反射对象创建我们可以使用反射动态创建类的对象。通过调用其中一个构造函数。然后我们可以访问对象的字段的值,...
Java JSON教程 -JSON模式像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用...