如何在CriteriaBuilder调用链中检查值是否为空?解决空指针访问异常的方案
Hey there! I see you're running into a null pointer issue when using CriteriaBuilder because some House entries have a null adressInfo, and you need your query to include those null-address houses plus only the ones where the street name is "A". Let's break down how to solve this cleanly.
The Problem with Your Current Code
Your existing line:
predicates.add(cb.equal(house.get("adressInfo").get("streetname"), value))
Throws a null pointer when adressInfo is null because you can't call .get("streetname") on a null object. Worse, it filters out all houses with no address info entirely — which is the opposite of what you want.
Solution: Use Left Join + OR Condition
The key here is to use a left join to preserve all House records (even those with null adressInfo), then combine two conditions with an OR:
- The house has an
adressInfowherestreetnameequals "A" - The house's
adressInfois null
Here's how to implement this:
Step 1: Create a Left Join for Address Info
First, set up a left join between House and adressInfo in your query. This ensures every house is included, regardless of whether it has address data:
Root<House> house = query.from(House.class); // Left join keeps all House records, even if adressInfo is null Join<House, AddressInfo> addressJoin = house.join("adressInfo", JoinType.LEFT);
Step 2: Build Your Filter Predicates
Next, create the two conditions we need and combine them with an OR:
// Condition 1: Street name matches "A" (only applies if adressInfo exists) Predicate streetNameMatch = cb.equal(addressJoin.get("streetname"), "A"); // Condition 2: adressInfo is null Predicate addressIsNull = cb.isNull(house.get("adressInfo")); // Combine both conditions with OR: include either case Predicate finalFilter = cb.or(streetNameMatch, addressIsNull); // Add the final filter to your predicates list predicates.add(finalFilter);
Why This Works
- The left join ensures that even houses with no
adressInfoare retained in the query results. - The
ORcondition lets you include both:- Houses with valid address info where the street is "A"
- All houses where address info is missing entirely
Alternative: No Join (But Less Reliable)
If you prefer not to use a join, you might think of using a direct OR with null check, but be careful:
// This can still throw a null pointer if adressInfo is null! Predicate riskyFilter = cb.or( cb.isNull(house.get("adressInfo")), cb.equal(house.get("adressInfo").get("streetname"), "A") );
The issue here is that the JPA provider might still attempt to resolve house.get("adressInfo").get("streetname") even when adressInfo is null, leading to the same error. The left join method is far safer and more readable.
Final Notes
- Double-check the spelling of "adressInfo" — did you mean "addressInfo"? A typo here could cause unexpected issues!
- This approach will return exactly what you need: all houses with no address info, plus only those with address info where the street is "A".
内容的提问来源于stack exchange,提问作者JSB

