I'm using MongoRepository interface to extend my custom repositories for different entities. Now I faced with problem, let's assume an example: I have 2 entities:
@Document(collection = "person")
public class Employee {
private String position;
}
and
@Document(collection = "person")
public class Manager {
private String major;
}
repositories for both:
@Repository
public interface ManagerRepository extends MongoRepository<Manager, String> {}
and
@Repository
public interface EmployeeRepository extends MongoRepository<Employee, String> {}
Everything goes well when I saving 2 models:
{
"_id" : ObjectId("5541f988d4c603ebac18a147"),
"_class" : "com.igmtechnology.gravity.core.init.test.Manager",
"major" : "majority"
}
{
"_id" : ObjectId("5541f988d4c603ebac18a148"),
"_class" : "com.igmtechnology.gravity.core.init.test.Employee",
"position" : "developer"
}
But when I'm doing findAll() from one of repositories I'm getting 2 objects and one of them spring is automatically casting to another one. How can avoid this auto casting? Or how can specify which class I need to get?
CrudRepository provides CRUD functions. PagingAndSortingRepository provides methods to do pagination and sort records. JpaRepository provides JPA related methods such as flushing the persistence context and delete records in a batch.
Spring @Repository annotation is used to indicate that the class provides the mechanism for storage, retrieval, search, update and delete operation on objects.
We don't. It is redundant to annotate the interfaces/classes with @Repository which extend/implement JpaRepository or some other predefined interfaces extending Repository , both because of @EnableJpaRepositories and the fact that they extend/implement Repository interface.
It is indeed not necessary to put the @Repository annotation on interfaces that extend JpaRepository ; Spring recognizes the repositories by the fact that they extend one of the predefined Repository interfaces.
For both of the repositories, you can use the @Query
annotation to specify a MongoDB JSON query string that will be used instead of query derived from the method's name (you must know that there's a convention for parsing the repository's method names and for building MongoDB queries).
So, by using @Query
, you can do:
@Repository
public interface ManagerRepository extends MongoRepository<Employee, String>
@Query(value="{ '_class' : 'com.igmtechnology.gravity.core.init.test.Manager' }")
List<Person> findAllManagers();
}
Behind the scenes, this will generate a query, similar to this one:
db.person.findAll({'_class' ; 'com.igmtechnology.gravity.core.init.test.Manager'});
However, there's a minor problem with this code. If you change the fully-qualified class name of Manager
, then the query would not throw a RuntimeException
, but would return nothing. In this case you can use a wildcard within the @Query
.
@Query(value="{ '_class' : ?0 }")
List<Person> findAllManagers(String className);
Then, when you invoke the method, you can just do:
managerRepository.findAllManagers(Manager.class.getName());
The provided Manager.class.getName()
will replace the ?0
wildcard and your query will built properly.
Same goes for the Employee
repository with the difference that you have to provide the fully-qualified class name of Employee
in the @Query
's value
attribute.
More info:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With