#Cacheable for default spring data jpa methods without overriding them - spring

Sry, if my question isn't new but i couldn't find answer.I use Spring Data JPA and Spring Cache.
I have folowing repository
#CacheConfig(cacheNames = "Category")
#Cacheable
#Repository
public interface Repository extends CrudRepository<Category, Long> {
Category findByCategory(String Category);
}
And i want to cache default CrudRepository methods, like findAll() and etc.
It's work If i override them like this
#CacheConfig(cacheNames = "Category")
#Cacheable
#Repository
public interface Repository extends CrudRepository<Category, Long> {
Category findByCategory(String Category);
List<Category> findAll();
}
But it's not convenient override them every time for every repository.
Is there a way cache defaults spring jpa methods without override them or no such way?

Yes, we can do it. Basically, Spring uses Hibernate ORM as the implementation of JPA. Hibernate itself supports caching functionality with it and will integrate better than Spring Cache.
To enable L2 cache, add these properties to your project add the following properties.
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.use_query_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
and dependencies hibernate-ehcache
Once this is done, all your default methods of JPA like findOne(), findAll() will be cached.
If you add any custom methods, you can add like below:
#QueryHints({ #QueryHint(name = "org.hibernate.cacheable", value ="true") }) Category findByCategory(String Category);
To test where default methods are cached, you can use the following properties to see if SQL has been executed.
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

Related

What is the difference between #Entity and #Document in spring boot?

Can you use both annotations on your database tables?
id, just like some clarification on there differences. thank you
#Entity is used to map a class to a relational database, it represents a database table.
#Document is used to map a class to noSQL database (specifically mongoDB), it represents a MongoDB documents.
You can use both JPA or MongoRepository if you are using both databases by creating different entities and repositories for each database.
I recommend you to have a look at spring documentation (https://docs.spring.io/spring-data/jpa/docs/current/reference/html/)
#Document is a Spring Data Mongo annotation while #Entity is part of Java Persistence API (JPA).
You can check both documentations:
Spring Data Mongo docs
JPA docs
Where into "Example 10. Repository definitions using domain classes with annotations" there is this piece of code:
interface PersonRepository extends Repository<Person, Long> { … }
#Entity
class Person { … }
interface UserRepository extends Repository<User, Long> { … }
#Document
class User { … }
And documentation says:
PersonRepository references Person, which is annotated with the JPA #Entity annotation, so this repository clearly belongs to Spring Data JPA. UserRepository references User, which is annotated with Spring Data MongoDB’s #Document annotation.
So you can see here the difference.

Writing generic spring jpa repository for all entities

I am working on Spring Boot application.
We have Service Layer,Rest Controller and Dao as repository.
I have 20 to 30 tables in my database and I dont want to create repository for each entity and extends that to CrudRepository.
ex : User is an Entity, to perform persistance operations on User, I have to create UserRepository which extends CrudRepository.
Same with Department, Company etc...
What i want to do is, I will write a BaseRepository which gonna extend CrudRepository, base repository should accept all entities and do persistance operations.
Is there a way to that ??
Don't extend CrudRepository it's functionality is all tied to the generic type, it'd be hacky to extend it for a generic implementation. You probably just want something simple which uses the JPA entity manager directly:
import javax.persistence.EntityManager;
import org.springframework.beans.factory.annotation.Autowired;
public class GenericRepository {
#Autowired
private EntityManager entityManager;
public <T, ID> T findById(Class<T> type, ID id) {
return entityManager.find(type, id);
}
}

Spring Data MongoDB add common criteria

I'm using Spring Data MongoDB repository abstraction to access mongoDB database:
public interface CustomerRepository extends MongoRepository<Customer, String> {}
...
#Autowired
private CustomerRepository customerRepository;
List<Customer> customers = customerRepository.findAll();
this will fetch all customers from mongoDB collection.
I'd like to add criteria for all CustomerRepository methods to filter customers by{"active": true} (the actual filter is more complicated if it's matter) transparently (without changing interface).
I'm thinking about overriding some base Spring Data MongoDB classes but I'm not sure how to do it.
Thanks.

Deciding which implementation to inject

I have a Spring project, split into several modules.
data access library (spring-data-jpa; entities and repositories)
security library (spring-security; including an extended repository with #PreAuthorize annotations)
web project (depends on both libraries)
batch project (depends only on data, since there's no user to authenticate in Spring)
So in the data access library, I have this interface:
#Repository
public interface ItemRepository extends PagingAndSortingRepository<Item, Long> {
List<Item> findAll();
Item findById(Long id);
}
And in the security library:
#Repository
public interface SecuredItemRepository extends ItemRepository {
#PreAuthorize("hasRole('ROLE_ADMIN')")
List<Item> findAll();
#PreAuthorize("hasRole('ROLE_ADMIN')")
Item findById(Long id);
}
When I #Autowire an ItemRepository, I would like it to use SecuredItemRepository if it's available, and ItemRepository if not.
Is there a way to declare the SecuredItemRepository as the default choice, or first in the list of ItemRepository implementations to grab? I'd rather not specify the implementation in every location that I need to access the database.
And of course, two seconds later I find the answer. I needed to annotate SecuredItemRepository with this:
#Priority(value = Ordered.HIGHEST_PRECEDENCE)

Spring DomainClassConverter Cache

I'm using spring-data-jpa, and I'm trying to apply spring cache abstraction.
findByEmail() method caches well, however, user variable on retrieve() method at controller which spring-data-jpa provide DomainClassConverter always looks up DB.
In documentation, it calles findOne() to look up the resource, but the #Cacheable trigger won't work.
It seems like implementation class as SimpleJpaRepository just invoke CrudRepository instead of UserRepository which I created and put #Cacheable annotation.
Is there any way to apply #Cacheable to findOne() except for custom DomainClassConverter class ?
UserController.class
#RequestMapping(method = RequestMethod.GET, value = "/users/{user}")
public ResponseEntity retrieve(#PathVariable User user) {
logger.info("Retrieve: " + user);
return new ResponseEntity(user.toUserResponse(), HttpStatus.OK);
}
UserService.class
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
#Cacheable("Users")
User findOne(Long id);
#Cacheable("Users")
User findByEmail(String email);
User findByEmailAndPassword(String email, String password);
Long countByEmail(String email);
}
I've filed and fixed DATACMNS-620 for you.
This issue shouldn't actually occur with Spring Data Commons 1.10.0 M1 (Fowler) as we moved to the Spring Data REST RepositoryInvokerAPI which explicitly checked for custom overrides. I created a fix for the 1.9.x bugfix branch so that we fix this for users of the current release train Evans.
If you want to check this upgrade to Spring Data Commons 1.9.0.BUILD-SNAPSHOT or 1.10.0.BUILD-SNAPSHOT. If you're using Boot, you can simply set a property spring-data-releasetrain.version and set it to either Evans-BUILD-SNAPSHOT or Fowler-BUILD-SNAPSHOT.

Resources