Hibernate关联查询需求:基于指定实体类编写带Join的HQL
Got it, let's break this down step by step. First, we'll fill in the missing Employee entity class (since it's linked to your TaxReturn entity), then we'll walk through practical Hibernate join query examples using both HQL and the Criteria API.
Step 1: Complete the Employee Entity
Since TaxReturn has a @OneToMany relationship with Employee, we need to define the inverse @ManyToOne side in Employee to properly map the association. Here's how it should look:
@Entity @Table(name = "employee") // Replace with your actual table name public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @Column(name = "employee_name") // Adjust column names to match your schema private String name; @Column(name = "annual_salary") private BigDecimal annualSalary; // Inverse side of the @OneToMany relationship with TaxReturn @ManyToOne(fetch = FetchType.LAZY) // LAZY is recommended for performance @JoinColumn(name = "tax_id", nullable = false) private TaxReturn taxReturn; // Don't forget to add constructors, getters, and setters in your actual code }
Step 2: Hibernate Join Query Examples
We'll cover two common approaches: HQL (Hibernate Query Language) and the Criteria API.
HQL Queries (Object-Oriented Syntax)
HQL is great for writing readable, object-focused queries.
1. Basic Join Query (Fetch TaxReturn + Associated Employees)
This query explicitly joins TaxReturn with its employees and returns both entities:
SELECT tr, emp FROM TaxReturn tr JOIN tr.employees emp
To avoid the N+1 query problem (loading TaxReturns first, then fetching employees one by one), use a fetch join:
SELECT tr FROM TaxReturn tr JOIN FETCH tr.employees emp
This loads all TaxReturns and their associated employees in a single database query.
2. Filtered Join Query (With Conditions)
If you need to filter results (e.g., get TaxReturns for a specific filing period and their employees):
SELECT tr, emp FROM TaxReturn tr JOIN tr.employees emp WHERE tr.fillingPeriod = :filingPeriod
Here's how you'd execute this in code:
try (Session session = sessionFactory.openSession()) { String hql = "SELECT tr, emp FROM TaxReturn tr JOIN tr.employees emp WHERE tr.fillingPeriod = :filingPeriod"; Query<Object[]> query = session.createQuery(hql, Object[].class); query.setParameter("filingPeriod", "2024-Q2"); List<Object[]> results = query.list(); for (Object[] result : results) { TaxReturn taxReturn = (TaxReturn) result[0]; Employee employee = (Employee) result[1]; // Add your business logic here } }
Criteria API Queries (Type-Safe)
If you prefer type-safe queries (no string-based HQL), use the Criteria API:
1. Basic Join Query
try (Session session = sessionFactory.openSession()) { CriteriaBuilder cb = session.getCriteriaBuilder(); CriteriaQuery<Object[]> cq = cb.createQuery(Object[].class); // Root entity: TaxReturn Root<TaxReturn> taxRoot = cq.from(TaxReturn.class); // Join with Employee entity Join<TaxReturn, Employee> empJoin = taxRoot.join("employees"); // Select both TaxReturn and Employee cq.select(cb.array(taxRoot, empJoin)); List<Object[]> results = session.createQuery(cq).getResultList(); // Process results as needed }
2. Filtered Join Query
Add a condition to filter by filing period:
try (Session session = sessionFactory.openSession()) { CriteriaBuilder cb = session.getCriteriaBuilder(); CriteriaQuery<Object[]> cq = cb.createQuery(Object[].class); Root<TaxReturn> taxRoot = cq.from(TaxReturn.class); Join<TaxReturn, Employee> empJoin = taxRoot.join("employees"); // Add filter condition Predicate periodFilter = cb.equal(taxRoot.get("fillingPeriod"), "2024-Q2"); cq.where(periodFilter); cq.select(cb.array(taxRoot, empJoin)); List<Object[]> results = session.createQuery(cq).getResultList(); }
Key Notes
- Fetch Type: For the
@ManyToOnein Employee,FetchType.LAZYis the default and recommended choice—it avoids loading the TaxReturn entity unless explicitly needed, which boosts performance. - Fetch Joins: Use
JOIN FETCHin HQL when you want to load associated entities in a single query to prevent N+1 issues.
内容的提问来源于stack exchange,提问作者ashley

