BaseCrudRepository findById returns null when the record exists

Viewed 56

I've encountered a problem with spring where a call to the repository findById(id) returns null. The record in question exists in the postgresql database, and my call to return pages of records works correctly. This is implemented via Classes which extend BaseCrudService and BaseCrudRepository. In the case with the problem, the controller calls the BaseCrudService function directly. It is not overridden in the extended classes. I have implemented the same code for two similar classes and underlying tables and it works okay. I cannot find what is different with this one.

'id' in the table is a unique numeric.

Code in Controller which extends PageCrudController

@RestController @RequestMapping(API_ENDPOINT) public class WildlifeController extends PageCrudController<Wildlife, Long, WildlifeView> {

private static final Logger LOG = LoggerFactory.getLogger(WildlifeController.class);

private final WildlifeService service;
private final WildlifeValidation validation;

@Autowired
protected WildlifeController(final WildlifeMapper mapper, final WildlifeService service, final WildlifeValidation validation ) {
    super(API_ENDPOINT, mapper, service);
    this.service = service;
    this.validation = validation;
}

@GetMapping
@PreAuthorize(HAS_AUTHORITY_READ)
public ResponseEntity<Page<WildlifePageView>> findPage(@SortDefault(sort = DEFAULT_SORT_FIELD) Pageable pageable ) {
    LOG.debug("Find Wildlife by Pageable: {}", pageable);
    // Return only results for authenticated user's aerodrome
    Aerodrome aerodrome = Objects.requireNonNull(SecurityContext.getPrincipal()).getAerodrome();
    Page<WildlifePageView> result = service.findPageByAerodrome(aerodrome, pageable, WildlifePageView.class);
    return ResponseEntity.ok(result);
}

@GetMapping("/{id}")
@PreAuthorize(HAS_AUTHORITY_READ)
public ResponseEntity<WildlifeView> find(@PathVariable("id") Long id) {
    LOG.debug("Find Wildlife by id: {}", id);
    Wildlife result = service.find(id);
    LOG.debug("Found Wildlife by id: {} = {}", id, result);
    return Optional.ofNullable(result).map(this::responseOk)
            .orElse(responseNotFound());
}

@PostMapping()
@PreAuthorize(HAS_AUTHORITY_WRITE)
public ResponseEntity<WildlifeView> create(@Valid @RequestBody WildlifeView view) {
    LOG.debug("Create Wildlife by view: {}", view);
    validation.validate(view);
    return super.doCreate(view);
}

@PutMapping("/{id}")
@PreAuthorize(HAS_AUTHORITY_WRITE)
public ResponseEntity<WildlifeView> update(@PathVariable("id") Long id, @Valid @RequestBody WildlifeView view) {
    LOG.debug("Update Wildlife '{}' by view: {}", id, view);
    validation.validate(view);
    return super.doUpdate(id, view);
}

@DeleteMapping("/{id}")
@PreAuthorize(HAS_AUTHORITY_WRITE)
public ResponseEntity<WildlifeView> delete(@PathVariable("id") Long id) {
    LOG.debug("Delete Wildlife by ID: {}", id);
    validation.validate(id);
    return super.doDelete(id);
}

}

Code in BaseCrudService - I've added the debug statements.

@Transactional(readOnly = true)
public E find(final ID id) {
    LOG.debug("Find with ID: {}", id);
    LOG.debug("Find with ID: {} count {}", id, this.repository.count());
    return repository.findById(id).orElse(null);
}
1 Answers

Found my problem. I had an an entity property marked nullable = false mapped to a nullable database table. The data set I was using had nulls in this column which prevents it from being read.

Broken:

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "cntrl_msrs_tkn_1_id", nullable = false)
private LutTabWlcm controlMeasuresTaken1;

Fixed

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "cntrl_msrs_tkn_1_id")
private LutTabWlcm controlMeasuresTaken1;
Related