Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Could any one tell me the real reason of spring-data projection in my case?

The case is: I have a repository and two methods, one of them looks like:

//There is no warning about: Activity domain type or valid projection interface expected here...
@Query("select distinct a.creatorId from Activity a")
Optional<List<String>> findAllCreatorIds();

The second method looks like:

//There i have warning about: Activity domain type or valid projection interface expected here
@Query("select distinct a.creatorId from Activity a join a.categories c where c.name in ?1")
Optional<List<String>> findAllCreatorIdsByCategoryNames(Set<String> categoryNames);

It looks workable and tests are passed and the generated query is the following:

SELECT DISTINCT activity0_.created_by AS col_0_0_
FROM activities activity0_
INNER JOIN category_item categories1_ ON 
activity0_.id=categories1_.activity_id
INNER JOIN categories category2_ ON 
categories1_.category_id=category2_.id
WHERE category2_.name IN (?)

I have made the changes to use projection interface. The simple projection interface is:

public interface CreatorIdProjection {
    String getCreatorId();
}

The query was changed:

@Query("select a from Activity a join a.categories c where c.name in ?1")
Optional<List<CreatorIdProjection>> findAllCreatorIdsByCategoryNames(Set<String> categoryNames);

Works too. And here is the generated query:

SELECT activity0_.id AS id1_0_,
       activity0_.price AS price2_0_,
       activity0_.created_by AS created_3_0_,
       activity0_.expiration_date AS expirati4_0_,
       activity0_.insertts AS insertts5_0_,
       activity0_.name AS name6_0_,
       activity0_.start_date AS start_da7_0_,
       activity0_.updatets AS updatets8_0_
FROM activities activity0_
INNER JOIN category_item categories1_ ON activity0_.id=categories1_.activity_id
INNER JOIN categories category2_ ON categories1_.category_id=category2_.id
WHERE category2_.name IN (?)

I have a few questions related to this case:

  1. Why there is no warning for the first method ?

  2. Why the query have a lot of fields after SELECT when we use projection? (to be more precise - why we cannot use "select a.creatorId from Activity a...")

  3. What is the reason of the warning "...domain type or valid projection interface expected here" if as a result we have a query that querying the table data instead of what we need.

like image 588
Hasty Bit Avatar asked May 23 '17 09:05

Hasty Bit


People also ask

What are projections in spring data?

Projection is one of the first things you're probably thinking about when implementing a query with Spring Data JPA. This is because projection defines the entity attributes and the database columns returned by your query. So, selecting the right columns is important for your business logic.

What is spring data and why it more powerful?

Spring Data is a high level SpringSource project whose purpose is to unify and ease the access to different kinds of persistence stores, both relational database systems and NoSQL data stores.

What is correct about Spring data JP A?

Spring Data JPA is an add-onIt provides a framework that works with JPA and provides a complete abstraction over the Data Access Layer. Spring Data JPA brings in the concept of JPA Repositories, a set of Interfaces that defines query methods. The Repository and Entity Bean represent the DAO layer in the application.

What are projections in Java?

Java Projections are pure Java classes that serve as proxies for Caché classes within a Java application. They provide the communication link between Java client objects and the Caché Objects on the Caché data server. Typically, a Java application contains a Java projection for each Caché class in the database.


2 Answers

The warning comes because you're using 'By' in your method name which triggers Spring Data to use (magic) Query methods.

Remove 'By' or replace it with 'Using' or something else and the warning will disappear.

See also https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.details

like image 51
Stephan Janssen Avatar answered Oct 14 '22 02:10

Stephan Janssen


About question #1:

Why there is no warning for the first method?

There is no Spring Data Projection involved here. You just execute a query returning a list of scalar values, that then is past on (and wrapped in an Optional) by Spring Data. Therefore you should not get such a warning. As a matter of fact I couldn't reproduce the warning at all, nor could I find it in the source code and in any case, the same argument holds for the second method. If it actually produces such a warning please submit a bug.

For question #2a

Why the query have a lot of fields after SELECT when we use projection?

You specify the query exactly using the @Query annotation, and it gets executed as such. Spring Data does not parse your query and removes unnecessary parts, which would be a huge amount of effort for little effect since you provided the query in the first place you might as well provide one that fits your needs.

For question #2b

why we cannot use select a.creatorId from Activity a...?

You can (almost). You just have to specify aliases because JPA will otherwise mangle the column names and Spring Data wouldn't know what columns it is looking at. It actually tells you so when you don't specify aliases. You should get an exception No aliases found in result tuple! Make sure your query defines aliases!. So this should work:

select a.creatorId as creatorId from Activity a...

An alternative is to actually invoke the constructor of a class in the statement:

@Query("select new my.super.cool.projection.CreatorId(a.creatorId)")

Both variants will only query the columns specified.

For question #3

What is the reason for the warning ...domain type or valid projection interface expected here if as a result we have a query that querying the table data instead of what we need.

I was not able to reproduce the warning. I also searched the source code and couldn't find it, so I can't answer this one.

like image 4
Jens Schauder Avatar answered Oct 14 '22 01:10

Jens Schauder