You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JPA EclipseLink中调用无主键实体类并实现非ID字段查询?

Hey there! Let's work through this query problem you're facing with your Header and LineItem entities. It's super frustrating when you're stuck only being able to fetch LineItems via Header ID—let's get you set up to query by other fields like name or customer account.

First, let's make sure your entity mappings are solid (sometimes wonky mappings can block proper queries). Here's a quick example of how your entities should look with correct OneToMany/ManyToOne associations:

Example Entity Mappings

// Header.java
@Entity
public class Header {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String customerAccount; // The customer account field you want to query by
    
    @OneToMany(mappedBy = "header", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<LineItem> lineItems = new ArrayList<>();
    
    // Getters, setters, constructors
}

// LineItem.java
@Entity
public class LineItem {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name; // The name field you want to query by
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "header_id") // Make sure this matches your DB foreign key column
    private Header header;
    
    // Getters, setters, constructors
}

Now, let's cover the most common ways to run your desired queries:

1. JPQL Queries (Most Straightforward)

JPQL lets you write queries using your entity class names and property names (not database column names—this is a common gotcha!).

Query LineItem by Name

EntityManager em = // Get your EntityManager instance
String jpql = "SELECT li FROM LineItem li WHERE li.name = :lineItemName";
TypedQuery<LineItem> query = em.createQuery(jpql, LineItem.class);
query.setParameter("lineItemName", "Your Target Name");
List<LineItem> results = query.getResultList();

Query LineItem by Header's Customer Account

Since customer account lives on Header, you'll join the two entities in your JPQL:

String jpql = "SELECT li FROM LineItem li JOIN li.header h WHERE h.customerAccount = :accountNumber";
TypedQuery<LineItem> query = em.createQuery(jpql, LineItem.class);
query.setParameter("accountNumber", "CUST-12345");
List<LineItem> results = query.getResultList();

2. Criteria API (Great for Dynamic Queries)

If you need to build queries on the fly (e.g., optional filters for name AND/OR customer account), the Criteria API is perfect:

Example: Dynamic Filter for Name or Customer Account

EntityManager em = // Get your EntityManager instance
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<LineItem> cq = cb.createQuery(LineItem.class);
Root<LineItem> lineItemRoot = cq.from(LineItem.class);

// Build predicates for your filters
List<Predicate> predicates = new ArrayList<>();

// Add filter for name if needed
String targetName = "Widget";
if (targetName != null) {
    predicates.add(cb.equal(lineItemRoot.get("name"), targetName));
}

// Add filter for customer account if needed
String targetAccount = "CUST-12345";
if (targetAccount != null) {
    Join<LineItem, Header> headerJoin = lineItemRoot.join("header");
    predicates.add(cb.equal(headerJoin.get("customerAccount"), targetAccount));
}

cq.where(cb.and(predicates.toArray(new Predicate[0])));
List<LineItem> results = em.createQuery(cq).getResultList();

3. Spring Data JPA Method Name Queries (If You're Using Spring)

If your project uses Spring Data JPA, you can define query methods directly in your repository interface—no need to write JPQL:

public interface LineItemRepository extends JpaRepository<LineItem, Long> {
    // Find LineItems by name
    List<LineItem> findByName(String name);
    
    // Find LineItems by Header's customer account
    List<LineItem> findByHeaderCustomerAccount(String customerAccount);
    
    // Combine filters (e.g., name AND customer account)
    List<LineItem> findByNameAndHeaderCustomerAccount(String name, String customerAccount);
}

Quick Troubleshooting Tips

  • Double-check that you're using entity property names (not database column names) in your queries. For example, if your LineItem's name field is called itemName in the entity, use that instead of item_name.
  • If you're getting lazy loading exceptions when accessing Header fields, make sure your query joins the Header entity (like in the JPQL example above) or use FetchType.EAGER (though EAGER fetching isn't always ideal—join fetch is better for performance).
  • Verify that your EntityManager is properly configured and that you're committing transactions if needed (for write operations, but queries usually don't require it unless you're using extended persistence contexts).

内容的提问来源于stack exchange,提问作者user9454796

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:04:08