JPA一对多查询是指在一个实体中有一个属性是另一个实体的集合,这种关系被称为一对多关系。JPA提供了一些API来帮助我们实现这种关系,以便我们可以使用JPQL语句来查询数据库中的数据。
要实现JPA一对多查询,首先需要在实体之间建立关联。在JPA中,有两种方式可以建立实体之间的关联:@OneToMany注释和@ManyToOne注释。@OneToMany注释用于表明一个实体有多个相关的实体,而@ManyToOne注释则表明多个实体都有相同的相关实体。
// 定义Department 实体 @Entity public class Department { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // 声明Employee 和 Department 的一对多关联 @OneToMany(mappedBy = "department") private List<Employee> employees; // getter and setter ... } // 定义 Employee 实体 @Entity public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // 声明Employee 和 Department 的多对一关联 @ManyToOne private Department department; // getter and setter ... }
当我们已经建立了实体之间的关联后,就可以使用JPQL语句来执行JPA一对多查询了。例如,如果要查询所有部门中员工的姓名,可以使用如下JPQL语句:
SELECT e.name FROM Department d JOIN d.employees e
以下JPQL显示如何在一对多映射中使用IN运算符。
executeAndPrintQuery("SELECT DISTINCT p FROM Employee e, IN(e.directs) p");
下面的代码来自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(); } }
以下代码来自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(); } }
以下代码来自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 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()); } }
下面的代码来自PersonDaoImpl.java。
package cn..common; import java.util.Arrays; import java.util.Date; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; 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); executeAndPrintQuery("SELECT DISTINCT p FROM Employee e, IN(e.directs) p"); } private void executeAndPrintQuery(String queryString) { try { Query query = em.createQuery(queryString); printQueryResult(queryString, query.getResultList()); } finally { em.close(); } } private void printQueryResult(String queryString, List result) { System.out.println("EJB QL: " + queryString+"n"); System.out.println("Result:n"); if (result.isEmpty()) { System.out.println("No results Foundn"); } else { for (Object o : result) { System.out.println(resultAsString(o)); } } } private String resultAsString(Object o) { if (o instanceof Object[]) { return Arrays.asList((Object[])o).toString(); } else { return String.valueOf(o); } } @PersistenceContext private EntityManager em; }下载 Query_In_OneToMany.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
Java格式 -Java 打印格式字符串使用Formatter格式化数据需要两种类型的输入:格式字符串值列表格式字符串定义如何格式化值列表。...
Java正则表达式教程 -Java正则表达式模式包 java.util.regex 包含三个类,以支持正则表达式的完整版本。模式匹配PatternSyntaxEx...
Java格式 -Java日期格式模式SimpleDateFormat日期和时间格式由日期和时间模式字符串指定。在格式字符串中,从“A到“Z和从“a到...
Java线程教程 -Java当前线程一个语句可以由不同的线程在不同的时间执行。Thread类静态方法currentThread()返回调用此方法的Threa...