✅ Short Answer
When you write a JPQL or native SQL query without explicitly including deleted = false, you risk retrieving soft-deleted rows, because without a @Where filter, your query doesn’t exclude them by default.
🔎 Detailed Explanation
🔹 What happens with @Where?
If you add @Where(clause="deleted=false") to your entity, Hibernate automatically appends AND deleted=false to all:
✅ Entity-level queries like em.find().
✅ HQL or Criteria queries on the entity itself (e.g., FROM User).
🔹 But what if you skip it in JPQL?
For example:
List<User> users = em.createQuery("SELECT u FROM User u", User.class).getResultList();
✅ If @Where is present → Hibernate adds deleted=false automatically.
❌ But if:
- You don’t use @Where, or
- Your query doesn’t target the entity directly, e.g., you query a DTO:
List<String> names = em.createQuery(
"SELECT u.name FROM User u", String.class).getResultList();
→ Hibernate doesn’t inject the deleted filter automatically, so you must manually add it:
List<String> names = em.createQuery(
"SELECT u.name FROM User u WHERE u.deleted=false", String.class).getResultList();
🔹 Native queries
If you use em.createNativeQuery(...), Hibernate has no idea about your entity’s mapping → @Where is ignored completely → you must always add deleted=false manually.
Example:
// Missing filter: may return soft-deleted rows!
List<Object[]> result = em.createNativeQuery("SELECT * FROM user").getResultList();
🔹 Why does this matter?
✅ Without filtering out deleted=true rows, your app could:
- Show deleted/inactive data to users → violating business rules.
- Process old, logically removed records.
📌 Key Takeaways
✅ @Where(deleted=false) automatically filters entity-based queries, but
❌ JPQL or native SQL without explicit deleted=false can include soft-deleted rows.
✅ Always double-check manual queries to ensure you exclude logically deleted data!