Load property of entity using spring-data-jpa query methods - java

For example, I have entity User with fields id, active and 10 more.
How could I get all active Users? Easy:
public interface UserRepository extends JpaRepository<User, Integer> {
List<User> findAllByActiveTrue();
}
How could I load list of id of active users? I need a #Query annotation to write JPQL by myself, like this:
public interface UserRepository extends JpaRepository<User, Integer> {
#Query("select u.id from User u where u.active = true")
List<Integer> fetchActiveUsersIds();
}
My question is: could I name somehow a method to avoid writing JQPL by myself, like in first case?
UPDATE
I need something like this:
public interface UserRepository extends JpaRepository<User, Integer> {
List<Integer> findAll_Id_ByActiveTrue();
}

I think that is not possible. The main purpose of Repositoryis to manage persistence of Domain Classes. It doesn't manage the properties independently. In the Spring Data Repositories documentation you can find a list of the methods available for CrudRepository.
You can compose your query using property extensions but it always returns the domain class for non aggregated methods.
For the specific use case you mention you'll need to use the #Query annotation.

Related

Spring Data JPA findAll with different EntityGraph

in Spring Data JPA Repository i need to specify multiple methods that do the same thing (eg. findAll) but specifying different #EntityGraph annotation (the goal is to have optimized methods to use in different services).
Es.
#Repository
public interface UserRepository extends JpaSpecificationExecutor<User>, JpaRepository<User, Long> {
#EntityGraph(attributePaths = { "roles" })
findAll[withRoles](Specification sp);
#EntityGraph(attributePaths = { "groups" })
findAll[withGroups](Specification sp);
etc...
}
In Java we can't have same method sign multiple times, so how to manage it?
Is it possible without using JPQL?
Thanks,
Gabriele
You can use EntityGraphJpaSpecificationExecutor to pass different entitygraph based on your method.
#Repository
public interface UserRepository extends JpaSpecificationExecutor<User>, JpaRepository<User, Long>, EntityGraphJpaSpecificationExecutor<User> {
}
In your service class, you can call find all with entity graph.
List<User> users = userRepository.findAll(specification, new NamedEntityGraph(EntityGraphType.FETCH, "graphName"))
Like above, you can use a different entity graph different based on your requirement.

How can i return only specific information with findAll() instead of everything?

for example i have Repository class :
public interface PersonRepo extends JpaRepository<Person, Long>, JpaSpecificationExecutor<Person>
and i want to use findAll() method provided by JpaSpecificationExecutor.
if i want to get all users it returns full user DTO-s including encripted passwords and user roles etc...
PersonRepo.findAll()
How can i tell findAll to send only name and email for example instead of everything.
I use Mapstruct to convert my Person Class to PersonDTO.
As mentioned here, you will have to define your own method and use the #Query annotation for it.

Spring Data JPA/Boot: findBy ... or

I want to write a finder method in my repository to find an object based on one field OR another one while supplying one parameter like:
#RepositoryDefinition(domainClass = Person.class, idClass = Long.class)
public interface PersonRepository extends CrudRepository<Person, Long> {
List<Person> findAllByIdOrAnotherId(someId);
}
How can I do that without using SQL?
I added a second parameter to the method and it worked.
List<Transaction> findAllByIdOrParentId(Long id, Long parentId);
This is just a definition for the method because I pass the same parameter to the method from the service as:
List<Transaction> transactions = transactionRepository.findAllByIdOrParentId(transactionId, transactionId);
One of the cool things about Spring Data JPA is the fact you can define custom queries as abstract methods in your interface.
In a nutshell, you can define a new search criteria just by specifying the #Entity field name you want to query by. So, let's say i want to findAll() by Id and CustomId. Both Id and CustomId are fields on my domain class. I would do:
List<Person> findAllByIdOrCustomId(someId, someCustomId);
For more info, research the link below:
Spring Data JPA - DEFINE QUERY METHODS

How to implement custom annotation with parameters that returns on calling the function? Like #Query

How to implement some thing like #Query method of Spring-Data-JPA-Repository?
Instead of using #Query, I want to use my own annotation, but it should work the exact same way as #Query does.
For example, the method should get parameters and return some data.
public interface UserRepository extends JpaRepository<User, Long> {
#Query("select u from User u where u.emailAddress = ?1")
User findByEmailAddress(String emailAddress);
}
Maybe I sound stupid, but I want to implement some thing similar to this.

How to turn off Query creation from method names in Spring JPA?

In Spring Data is it possible to turn off Query Generation from method names?
Given the interface
public interface UserRepository extends Repository<User, Long> {
List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);
}
I would want spring security to produce an error saying that generating queries from method names has been turned off please use the explicitly #Query annotation like so.
public interface UserRepository extends Repository<User, Long> {
#Query("select u from User u where u.emailAddress = ?1 and u.lastname = ?2")
List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);
}
I want to turn off the the automatic query generation because I think it is easier to read the query and know what is going on rather than reading the method name and translating to what is the query that Spring data will generate, also on a large team with lots of developers some who might not yet be familiar with spring data #Query is a lot more readable?
How to turn off Query creation from method names in Spring JPA?
You can specify the query-lookup-strategy on the repositories tag in the configuration.
<repositories query-lookup-strategy="use-declared-query"/>
See the documentation
User.java
#Entity
#NamedQuery(name="User.findByEmailAddressAndLastName",
query="select u from User u where u.emailAddress = ?1 and u.lastname = ?2")
public User{
}
UserRepository.java
public interface UserRepository extends Repository<User, Long> {
List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);
}
How Spring handles this is called the Query Lookup Strategy. Queries can be resolved by method names (CREATE), by manual queries (USE_DECLARED_QUERY), or both (CREATE_IF_NOT_FOUND) which defaults to method names if no manual query is found. USE_DECLARED_QUERY would give you the desired functionality, warning you if no manual query is specified.
As Kevin answered, this can be configured in xml. But as a more modern option, you can specify the lookup strategy when configuring your repository in a Java Config class with queryLookupStrategy parameter in the #Enable{store}Repositories annotation.
For example, to force manual queries, you could use the following:
#EnableJpaRepositories(queryLookupStrategy=QueryLookupStrategy.Key.USE_DECLARED_QUERY)
public class MyDatabaseConfig {
...
}
More info here
https://docs.spring.io/spring-data/jpa/docs/2.0.7.RELEASE/reference/html/#repositories.query-methods.query-lookup-strategies
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/query/QueryLookupStrategy.Key.html?is-external=true

Categories