In Container-Managed Persistence (CMP), the developer does not write SQL in Java code. The container generates persistence code automatically, but it still needs to know how to query the database. Without a query language, there’s no way to define finder queries in CMP without falling back to writing raw SQL in the bean class.
EJB-QL is an object-oriented query language used in CMP deployment descriptors to define finder and select queries. Unlike SQL which operates on tables and columns, EJB-QL operates on EJB abstract persistent fields and relationships.
- Queries are written in
ejb-jar.xmldeployment descriptor, not in Java code - Syntax:
SELECT OBJECT(p) FROM PRODUCTS p WHERE p.basePrice > ?1 prepresents the bean abstract schema, not a database table?1is a positional parameter passed from the finder method- Queries are parsed by the container and converted to actual SQL at deployment or runtime
- Because XML uses
<and>for tags, comparison operators must be wrapped in<![CDATA[ ... ]]>to avoid parser errors
- Object-oriented: operates on bean abstract schema names, not table/column names
- Defined in deployment descriptor, not Java source code
- Supports positional parameters (
?1,?2, etc.) for parameterized queries - Requires CDATA wrapping for comparison operators in XML
- Container translates EJB-QL to vendor-specific SQL
- Built from: CMP — EJB-QL is exclusive to CMP beans
- Builds into: CMP Abstract Accessors — EJB-QL queries are used by finder methods defined via abstract accessors
- Contrasts with: SQL — EJB-QL is object-based and in XML; SQL is table-based and in Java code (BMP)
- Related: EJB Deployment Descriptor — EJB-QL queries live inside the deployment descriptor
- Related: CDATA Hack — XML escaping needed for EJB-QL operators
- Forgetting CDATA wrapping causes XML parsing errors on operators like
>,<,>= - EJB-QL syntax differs from JPQL (Java Persistence Query Language) in later JPA specs
- EJB-QL only works with CMP 2.0+ entity beans; BMP beans use raw JDBC
- Queries are validated at deployment time, not at compile time