1

I have an entity called Person, inside that basic metadata, then inside that Tag and Language. I want to get all rows that contain specific tag name and language. I came to know about Criteria Query about. How can we interlink two different entities together?

Example: Get all rows having the tag as Model and language as English.

@Entity
public Person {
    @Id
    private String id;
    private BasicMetadata basicMetadata;
     -----------
}

Basic Metadata table

@Entity
public BasicMetadata {
   @Id
   private String id;
   private List<Tag> tags;
   private List<Language> language;
   -------------
}

Tag Table

@Entity
public Tag {
    @Id
    private String id;
    private String name;
    -------------

}

Language Table

@Entity
public Language{
    @Id
    private String id;
    private String name;
    -------------

}

I created a simple method for specification Query is that correct

 private Specification<Person> containsText(String keyword) {
    return (root,query, builder) -> {
        String finalText = keyword.toLowerCase();
        if (!finalText.contains("%")) {
            finalText = "%" + finalText + "%";
        }
        Predicate genreExp = builder.like(builder.lower(root.get("basicMetadata").get("tags")), finalText);
        return builder.or(genreExp);
    };
snieguu
  • 2,073
  • 2
  • 20
  • 39

1 Answers1

0

you can write your specification like this

public class PersonSpecifications {

   public static Specification<Person> hasTag(String keyword) {
        return (root, query, builder) -> {
           String finalText = keyword.toLowerCase();
           if (!finalText.contains("%")) {
              finalText = "%" + finalText + "%";
           }
           Join<Person, BasicMetaData> md = root.join("basicMetaData");
           return builder.like(builder.lower(md.join("tags").get("name")), finalText);
       }
  }
}

and you can use this specification to get the filtered results like this

 repository.findAll(PersonSpecifications. hasTag("abc"),PageRequest,of(0,10));
Reza Nasiri
  • 1,360
  • 1
  • 6
  • 19
  • But while using Person repository as `Page findAll(Specification containsText, Pageable pageRequest);`. After running the application error occured as `Caused by: org.springframework.data.mapping.PropertyReferenceException: No property findAll found for type Person!` – Nandakumar Kadavannoore Jan 03 '19 at 11:05
  • is your repository extending JpaSpecificationExecutor? – Reza Nasiri Jan 03 '19 at 12:40
  • Yes extending both `PagingAndSortingRepository` and`JpaSpecificationExecutor` – Nandakumar Kadavannoore Jan 04 '19 at 07:04
  • that doesn't seem right. can you share your repository code as well as the code that causing the exception? – Reza Nasiri Jan 04 '19 at 14:32
  • `public interface PersonRepository extends CrudRepository, JpaSpecificationExecutor { Page findAll(Specification containsText, Pageable pageRequest); Page findAll(Pageable pageable); }` – Nandakumar Kadavannoore Jan 07 '19 at 06:42
  • I have gone through documents found that issue maybe [link] (https://stackoverflow.com/questions/33735797/spring-data-mongodb-repository-jpa-specifications-like). I am using MongoDB.So I desired to use query annotation in JPA. Can suggest sample @Query for the question above ( Get all rows having the tag as Model and language like English.). Can I use inner joins and joins in a MongoDB database project – Nandakumar Kadavannoore Jan 07 '19 at 09:57
  • that is not how you use the specifications. see my updated answer and delete those two methods in the repository as you don't need them. – Reza Nasiri Jan 07 '19 at 12:55