0

I have looked at numerous examples and tried various w/ & w/o example matcher constraints but whatever I do my query by example only returns null.

I am able to get the CRUD Repository data calls to work without any issues, however I extended that to the JPA Repository and added the QueryByExampleExecutor interface. The findOne() does not seem to be working.

Using Spring Boot 2.2.6.RELEASE, spring-boot-starter-data-jpa and mysql 5.7.

When using query by example does the entire object need to be completed for matching? In other words, do all setters need the correct information? Or just the object data item that is to be matched?

And Yes, the database does contain only one correct string on which I am attempting to match.

Customer

@Entity
@Table(name="customer")
public class Customer {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id")
    private long id;

    @Column(name="social_security_number")
    private String socialSecurityNumber;

    //Other data fields are included
}

CustomerRepository

import org.springframework.data.jpa.repository.JpaRepository;

public interface CustomerRepository extends JpaRepository<Customer, Long> {
}

QueryByExampleExecutor

import java.util.Optional;

import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

public interface QueryByExampleExecutor<T> {

    <S extends T> Optional<S> findOne(Example<S> example);

    <S extends T> Iterable<S> findAll(Example<S> example);

    <S extends T> Iterable<S> findAll(Example<S> example, Sort sort);

    <S extends T> Page<S> findAll(Example<S> example, Pageable pageable);

    <S extends T> long count(Example<S> example);

    <S extends T> boolean exists(Example<S> example);

}

CustomerService

public interface CustomerService {
    public Customer findBySSN(String ssn);
}

CustomerServiceImpl

@Service
public class CustomerServiceImpl implements CustomerService {

private CustomerRepository customerRepository;

    @Autowired
    public CustomerServiceImpl(CustomerRepository theCustomerRepository) {
        customerRepository = theCustomerRepository;
    }

    @Override
    public Customer findBySSN(String ssn) {
        //Create a new object to use as a basis for querying against
        Customer customer = new Customer();
        //Set the parameters for the query
        customer.setSocialSecurityNumber(ssn);
        //Create an example query
        Example<Customer> customerExample = Example.of(customer);

        Optional<Customer> result = customerRepository.findOne(customerExample);

        if (result.isPresent()) { 
            return result.get();
        } else {
            // Didn't find the customer
            throw new ObjectNotFoundException("Customer", "Social Security Number ("+ssn+") not found...");
        }
    }
}

Calling Method

    @Autowired
    private CustomerService customerService;


    Customer ssnCustomer = customerService.findBySSN("123456789");
        if(ssnCustomer == null) {
            System.out.println("SSN NOT FOUND WAS NULL");
        } else {
            System.out.println("SSN FOUND "+ssnCustomer.getId());
        }

What am I missing? Thank you in advance.

kenny_k
  • 3,831
  • 5
  • 30
  • 41
Bill Snee
  • 119
  • 1
  • 11
  • I don't see customerRepository is initialized in your service class. and also can you elaborate more how did you check null value. If object is returned then you will get detail or your code with throw exception. – Satyendra Sharma Jun 03 '20 at 22:06
  • I have edit the service implementation to show the repository initialization. Sorry I forgot it previously. After the data call is made, my internal exception handler shows ===2020-06-03 21:16:20 WARN o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver.logException(199) - Resolved [com........exception.ObjectNotFoundException: Customer - Social Security Number (123456789) not found...] ==== I am also using some AOP for logging purposes and for this test I turned them off. – Bill Snee Jun 04 '20 at 01:18
  • With AOP == c.z.z.aop..aroundServicesAdvice(195) - CustomerServiceImpl.findBySSN(..) had an exception: Customer - SSN (123456789) not found.. c.z.z.aop...afterThrowingAdvice(172) - Running afterThrowingAdvice().. c.z.z.aop...logMethodSignatureAndArguments(240) - Method called: CustomerServiceImpl.findBySSN(..), Method signature: Customer ....service.CustomerServiceImpl.findBySSN(String) c.z.z.aop...logMethodSignatureAndArguments(248) - An argument was: 123456789 c.z.z.aop...afterThrowingAdvice(177) - An exception was thrown: Customer - Social Security Number (123456789) not found.. – Bill Snee Jun 04 '20 at 01:30
  • 1
    1) In entity class change id from long to Long. 2) To read data from repository call findOneBySocialSecurityNumber by passing ssn string. You don’t need to create an object to fetch record. – Alok Singh Jun 04 '20 at 02:21
  • @AlokSingh Thanks, I was previously able to create just the repository call and had it working. But wanted to try/use the Query by Example method I has also found. The key was changing all my primitives to Wrapper class as you suggested. – Bill Snee Jun 04 '20 at 03:20

1 Answers1

3

Change id type from long to Long. long is setting value as 0 automatically and making it part of query.

private Long id;

Change getter and Setter accordingly

  • Thank you for the suggestion. Even changing the ID to Long, and the getters and setters as well. There were no changes in the results. – Bill Snee Jun 04 '20 at 02:36
  • I ran code In my system and everything worked well. I got the result. have property set to : spring.jpa.show-sql: true. to see what exact query is hitting DB. – Satyendra Sharma Jun 04 '20 at 02:47
  • When I check query it was using ID because of long. Once I changed it to Long everything worked. – Satyendra Sharma Jun 04 '20 at 02:55
  • I had some extra fields that were also primitives besides just the id. After changing those, everything worked. – Bill Snee Jun 04 '20 at 03:10