We are using the Spring Data JPA for database access. Our repositories contain basic query methods. What we want to do now is to use the Specification-Interface (criteria API) combined with complex query methods (like findByName(Specification spec)). The problem is that these two ways block each other out (since there are two where queries now). Is there any way to do this, like telling JPA to combine the two where parts with AND? The reason we want to do this is because some parts of the where query are essential for every query. They should be defined in the name of the query method. The Specification only should contain individual criterias for individual use-cases.
Or is there any other way to solve this?
Currently this is not supported. Please feel free to raise a JIRA issue if you think this would be a worthwhile enhancement.
Related
I'm considering using spring-data-jdbc for a project.
But i don't have any control over the DB-schema.
My domain model can be populated by the existing tables, but they differ in many ways.
Examples:
A specific aggregate in my model consists of nested Value-Objects. The corresponding table only features flat columns, so the nested Value-Objects would have to be mapped manually.
One the other hand, there are aggregates that don't have many nested Value-Objects, but the corresponding tables are organized according to a star-schema, so the values are distributed over many tables (instead of a single one).
I guess this prevents me from using many of the Quality-Of-Life features (like Query-Derivation and Mapping).
Do I actually get anything significant out of spring-data-jdbc in comparison to using a plain JdbcTemplate in this scenario?
The scenario you describe would make me tend towards plain JdbcTemplate.
But I would consider using the Aggregate approach Spring Data JDBC does:
Load complete aggregates
Reference between aggregates using ids, or something like an AggregateReference
And if you have an aggregate that actually can be mapped using Spring Data JDBC you can still do that.
I am currently working on a project where I have to retrieve some rows from the database based on some filters (I also have to paginate them).
My solution was to make a function that generates the queries and to query the database directly (it works and it's fast)
When I presented this solution to the senior programmer he told me this is going to work but it's not a long-term solution and I should rather use Spring Specifications.
Now here comes my questions :
Why is Spring Specifications better than generating a query?
Is a query generated by Spring Specifications faster than a normal query?
Is it that big of a deal to use hard-coded queries ?
Is there a better approach to this problem ?
I have to mention that the tables in the database don't store a lot of data, the biggest one (which will be queried the least) has around 134.000 rows after 1 year since the application was launched.
The tables have indexes on the rows that we will use to filter.
A "function that generates the queries" sounds like building query strings by concatenating smaller parts based on conditions. Even presuming this is a JPQL query string and not a native SQL string that would be DB dependent, there are several problems:
you lose the IDEs help if you ever refactor your entities
not easy to modularize and reuse parts of the query generation logic (eg. if you want to extract a method that adds the same conditions to a bunch of different queries with different joins and aliases for the tables)
easy to break the syntax of the query by a typo (eg. "a=b" + "and c=d")
more difficult to debug
if your queries are native SQL then you also become dependent on a database (eg. maybe you want your integration tests to run on an in-memory DB while the production code is on a regular DB)
if in your project all the queries are generated in a way but yours is generated in a different way (without a good reason) then maintenance of the will be more difficult
JPA frameworks generate optimized queries for most common use cases, so generally speaking you'll get at least the same speed from a Specification query as you do from a native one. There are times when you need to write native SQL to further optimize a query but these are exceptional cases.
Yes, it's bad practice that makes maintenance a nightmare
I would like to know why we are using spring jpa specifications in spring boot application. I could see something like specifications (classname).and , .or these kind of operations what exactly it is?
Spring JPA specifications allow you to define a predicate (a part of WHERE clause of a query).
This helps you create complex queries in an object oriented style, allow you to create reusable predicates that you may use in different queries without repeating yourself, and it can help you create dynamic queries that can be constructed at runtime.
One example of a good use case for specifications is a search page with optional filtering criteria (think any eCommerce website). Using JPA specifications you can define a predicate for each filter and at runtime you can include in your query only the predicates that are related to the filters that the user has applied.
I have to make some filters, such as get persons who are in a given department, and I was wondering about the best way to do it.
Some of them are going to require the join of multiple tables.
Does anyone know about the main differences between CDbCriteria and Query Builder? I would particularly like to know about the compatibility with databases.
I found this in the Yii documentation about Query Builder:
It offers certain degree of DB abstraction, which simplifies migration to different DB platforms.
Is it the same for the CDbCriteria objects? Is it better?
The concept of CDbCriteria is used when working with Yii's active record (AR) abstraction (which is usually all of the time). AR requires that you have created models for the various tables in your database.
Query builder a very different way to access the database; in effect it is a structured wrapper that allows you to programmatically construct an SQL query instead of just writing it out as a string (as an added bonus it also offers a degree of database abstraction as you mention).
In a typical application there would be little to no need to use query builder because AR already provides a great deal of functionality and it also offers the same degree of database abstraction.
In some cases you might want to run a very specific type of query that is not convenient or performant to issue through AR. You then have two options:
If the query is fixed or almost fixed then you can simply issue it through DAO; in fact the query builder documentation mentions that "if your queries are simple, it is easier and faster to directly write SQL statements".
If the query needs to be dynamically constructed then query builder becomes a good fit for the job.
So as you can see, query builder is not all that useful most of the time. Only if you want to write very customized and at the same time dynamically constructed queries does it make sense to use it.
The example feature that you mention can and should be implemented using AR.
I would like to apply a Criteria query to an in-memory collection
of entities, instead of on the database. Is this possible?
To have Criteria API work like LINQ? Or alternatively, convert
Criteria query to LINQ query.
Thanks!
I don't believe you can use Criteria to query against an in-memory collection and come to think about it it doesn't seem to make much sense. If I'm understanding everything correctly you've already queried against your database. I'd suggest to either tune your original query (whichever method you choose) to include all of your filters. Or you could use LINQ (as you suggested) to refine your results.
Also, what's your reasoning for wanting to query from memory?
It sounds like you're rolling your own caching mechanism. I would highly recommend checking out NHibernate's 2nd level cache. It handles many complex scenarios gracefully such as invalidating query results on updates to the underlying tables.
http://ayende.com/Blog/archive/2009/04/24/nhibernate-2nd-level-cache.aspx