1

I feel like this should be pretty straightforward, but I'm not sure about the actual code for it. Basically, I have my rest controller taking in 6 arguments, passing that through the Service and then using those arguments to build the object inside of the ServiceImplementation. From there I return a call to my repo using the object I just made. This call should attempt to query the database specific parameters of the object.

This query is the part where I'm not sure how to write using Spring JPA standards. I'd like to just use the variables I set my object with, but I'm not sure if I'll have to write out a query or if spring JPA can make it a bit more simple?

Code:

Controller:

@RestController
public class exampleController {

    @Autowired
    private ExampleService exampleService;

    @GetMapping("/rest/example/search")
    public exampleObj searchExample (@RequestParam(value = "exLetter") String exLetter,
            @RequestParam(value = "exLang") String exLang, @RequestParam(value = "exType")int exType, 
            @RequestParam(value = "exMethod") String exMethod, @RequestParam(value = "exCd") String exCd,
            @RequestParam(value = "exOrg") String exOrg) {

        return exampleService.getExampleLetter(exLetter, exLang, exType, exMethod, exCd, exOrg);
    }
}

ExampleSerivce:

public interface ExampleService {

    public ExampleLetter getExampleLetter(String exLetter, String exLang, int exType, String exMethod, String exCd, String exOrg);
}

ExampleServiceImplementation:

@Service
public class ExampleServiceImpl implements ExampleService {
    @Autowired
    private ExampleRepository exampleRepo;

    @Override
    public ExampleLetter getExampleLetter(String exLetter, String exLang, int exType, String exMethod, String exCd, String exOrg) {

        ExampleLetter examp = new ExampleLetter();

        examp.setExCd(exCd);
        examp.getKey().setExampleNumber(exLetter);
        examp.getKey().setLanguageType(exLang);
        examp.getKey().setMethod(exMethod);
        examp.getKey().setMarketOrg(exOrg);
        examp.getKey().setType(exType);

        return exampleRepo.findExampleLetter(examp);
    }   
}

Repo:

@Repository
public interface ExampleRepository extends CrudRepository<ExampleLetter, ExampleLetterKey> {

}
Maze
  • 368
  • 3
  • 15

1 Answers1

1

If I understand it correctly, you are trying to make a dinamic query, based on filtering values that may or may not be there. If that's the case, you can use the Specification class to create the query dinamically:

First, in your Repository class, extend JpaSpecificationExecutor<ExampleLetter>:

@Repository
public interface ExampleRepository extends CrudRepository<ExampleLetter, ExampleLetterKey>, JpaSpecificationExecutor<ExampleLetter> {

}  

Now, you will need a method (I'd sugest you put it in an specific class, for organization sake) to generate the query itself:

public class GenerateQueryForExampleLetter {

    ExampleLetter exampleLetter;

    public Specification<ExampleLetter> generateQuery() {
        return new Specification<ExampleLetter>() {
            private static final long serialVersionUID = 1L;

            @Override
            public Predicate toPredicate(Root<ExampleLetter> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                Predicate pred = null;

                List<Predicate> predicates = new ArrayList<Predicate>();

                if (this.exampleLetter.getExCd()!= null && !this.exampleLetter.getExCd().isEmpty()) {
                    predicates.add(builder.equal(root.<String>get("exCd"), this.exampleLetter.getExCd()));
                }

    ...................

                if (this.exampleLetter.getTheFieldYouNeed()!= null && !getTheFieldYouNeed.isEmpty()) {
                    predicates.add(builder.equal(root.<TheTypeOfTheField>get("theFieldYouNeed"), this.exampleLetter.getTheFieldYouNeed()));
                }


                if (!predicates.isEmpty()) {
                    pred = builder.and(predicates.toArray(new Predicate[] {}));
                }

                return pred;
            }
        };
    }

    public void setExampleLetter (ExampleLetter el) {
        this.exampleLetter = el;
    }
}

Finally, in your service class:

@Override
public ExampleLetter getExampleLetter(String exLetter, String exLang, int exType, String exMethod, String exCd, String exOrg) {

    ExampleLetter examp = new ExampleLetter();

    examp.setExCd(exCd);
    examp.getKey().setExampleNumber(exLetter);
    examp.getKey().setLanguageType(exLang);
    examp.getKey().setMethod(exMethod);
    examp.getKey().setMarketOrg(exOrg);
    examp.getKey().setType(exType);

    GenerateQueryForExampleLetter queryGenerator = new GenerateQueryForExampleLetter ();

    queryGenerator.setExampleLetter(examp);

    return exampleRepo.findAll(queryGenerator.generateQuery());
}

Note that the JpaSpecificationExecutor interface adds a few utility methods for you to use which, besides filtering, supports sorting and pagination.

For more details, check here, here, or this answer.

  • Just read through what you typed out as well as the other items that you linked. Thank you for having such an extensive answer. This Query by Example looks extremely promising. – Maze Apr 22 '20 at 18:49
  • Thanks. If the answer solves your problem, please, don't forget to "accept" it :) , and if you have any problems or questions, just send them here. By the way, does the object ExampleLetter have an inner object called "Key"? – Guilherme Barboza Apr 22 '20 at 19:46
  • Yeah, it definitely does. Why do you ask? – Maze Apr 27 '20 at 08:15
  • Well, in this case, the solution would be a little more complex (would include a set of "OR" SQL clauses) but it seems you have everything sorted out. Anyways, if you have any problems, we're here to help. – Guilherme Barboza May 02 '20 at 19:42
  • Oh, yeah. Totally got it sorted out. Part of it was because I didn't actually create my key object within my example letter object. That's why I couldn't call my getkey() method. Otherwise most of the other code pretty much works. – Maze May 03 '20 at 20:03