3

Product and ProductTag form a one-to-many relationship, as shown below.

@Entity
public class Product {
    @Id
    Long id;

    @OneToMan(mappedBy = "product")
    List<ProductTag> productTags;
}

@Entity
public class ProductTag {
   @Id
   Long id;

   String content;

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "product_id")
   Product product;
}

Now I have an API that searches products, then returns them with their tags. Every time I call product.getProductTags(), Hibernate will fire an SQL query. Since the MySQL server is far away from the app server, I would like to cache product.getProductTags() call. How do I achieve that?

Chris Peng
  • 896
  • 1
  • 10
  • 23

2 Answers2

2

Use a specific query to fetch the tags and store them in a cache:

public TagRepository extends JpaRepository<Tag, Long> {

     @Cacheable("tagsByProducts")
     @Query("Select t from ProductTag t where t.product = ?product")
     List<Tag> findByProduct(Product product);

}

somewhere you need some method to evict the cache: annotated by@CacheEvict("tagsByProducts")

But to be honest: I doubt that is a good idea to store JPA Entities in a cache! I think this would lead to many many strange problems. So better query just for the tag names (or content) instead of the tag-entities.

public TagRepository extends JpaRepository<Tag, Long> {

     @Cacheable("tagsByProducts")
     @Query("Select t.content from ProductTag t where t.product = ?product")
     List<String> findTagContentByProduct(Product product);

}
Ralph
  • 118,862
  • 56
  • 287
  • 383
  • 1
    When I annotate the interface method with @Cacheable, the IDE gives a warning that "spring discourages annotating interfaces with Cache*," do you think is it something that worth concerning? – Chris Peng Dec 17 '19 at 08:05
  • 1
    @Chris Peng: The same technique is supposed by Oliver Drotbohm (Spring Data Project Lead) in https://stackoverflow.com/a/26283080/280244 - so I think write a test to make sure that it works, and then ignore the missleading IDE warning - and there is also a official spring data example https://github.com/spring-projects/spring-data-examples/blob/master/jpa/example/src/main/java/example/springdata/jpa/caching/CachingUserRepository.java that use that cache in this way – Ralph Dec 18 '19 at 07:33
0
  @Entity
  public class Product {
   @Id
   Long product_id;

   @OneToMany(casacade=CascadeType.ALL, 
  fetch=FetchType.Eager,mappedBy = "product")
   @JsonManagedReference(value="product-tag")
    List<ProductTag> productTags;
   }

 @Entity
 public class ProductTag {
 @Id
  Long id;

  String content;

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "product_id")
  @JsonBackReference(value="product-tag")
   Product product;
  }
Apoorva
  • 36
  • 5