Note that there are some explanatory texts on larger screens.

plurals
  1. POExposing Hibernate criteria via service API
    text
    copied!<p> This is more of a design than implementation question and it's going to be long so bear with me. It's best explained with an example: </p> <p> Let's say I have a business entity called <b>Product</b> with a bunch of properties (<b>name</b>, <b>price</b>, <b>vendor</b>, etc...). </p> <p> It's represented by an interface (<b>Product</b>) and implementation (<b>ProductImpl</b>, mapped in Hibernate) as well as basic CRUD service interface (<b>ProductService</b>) and implementation (<b>ProductServiceImpl</b>).<br /> <b>Product</b> and <b>ProductService</b> are exposed as API, their implementations are not. </p> <p> I want to add a <b>List findProducts(QueryCriteria criteria)</b> method to <b>ProductService</b> that would return a list of products satisfying given criteria. The requirements are: </p> <ol> <li>Query by direct <b>Product</b> properties (e.g. <code>product.price gt 50.0</code>)</li> <li>Query by association (e.g. <code>product.vendor.name = "Oracle"</code>)</li> <li>Sort results (e.g. <code>order by product.vendor.name desc, product.price asc"</code>)</li> <li>Apply additional filters. Unlike the above 3 items which are all specified by API client, additional filters may be applied by the service based on client's identity (e.g. client invoking this method may be limited to only seeing products manufactured by given vendor). Such filters take precedence over any criteria specified by the client (e.g. if the filter is set to <code>product.vendor.name = "Microsoft"</code>, query in (2) above should produce empty result set. </li> </ol> <p>The question, therefore, is what should <b>QueryCriteria</b> interface used by such a method look like? I can think of 3 solutions and I don't like either one of them:</p> <ul> <li>Allow clients to specify HQL (starting with "where" clause) directly. This is the most straightforward solution, but also the most problematic security-wise. Even assuming that filters (#4 above) are simple enough to be implemented via Hibernate's session filters, HQL still needs to be parsed to - at the very least - ensure that query parameters are specified as parameters and not inlined.</li> <li>Use thinly wrapped Hibernate's <b>DetachedCriteria</b> in place of <b>QueryCriteria</b>. "Thinly wrapped" because client can not be allowed to create <b>DetachedCriteria</b> directly for there would be no way to control what mapped entity it was created for. Also, this would not as flexible as HQL for some queries are not easily (or at all) expressible via Criteria API. As with HQL approach, filters (#4 above) will be limited to Hibernate session filters.</li> <li>Write my own <b>QueryCriteria</b> interface / implementation which will form either DetachedCriteria or HQL behind the scenes. While probably the most flexible solution, this will have to duplicate a lot of code from Criteria API which seems less than ideal.</li> </ul> <p>Any comments on the validity of the above approaches or - fingers crossed - simple elegant solutions that didn't occur to me would be highly appreciated. </p> <p>P.S. In my specific case, all API clients are internal and "semi-trusted" - that is I'm not as much concerned with someone trying to deliberately break something as with poor programming resulting in Cartesian product of 5 tables :-) However, it'd be nice to come up with a solution that would withstand API exposure to public.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload