I think Hibernate's lazy loading may be preventing my Controller from returning the appropriate response.
@RestController
@RequestMapping("/shifts")
public class ShiftController {
private ShiftService shiftService;
@Autowired
public ShiftController(ShiftService shiftService) {
this.shiftService = shiftService;
}
@GetMapping("")
@PreAuthorize("hasAnyAuthority('ADMIN','SUPERVISOR')")
Collection<Shift> getShifts() {
return shiftService.fetchAll();
}
@GetMapping("/{id}")
@PreAuthorize("hasAnyAuthority('ADMIN','SUPERVISOR')")
ResponseEntity<Shift> getOneShift(@PathVariable("id") Long id) {
Shift shift = shiftService.fetchOne(id);
return new ResponseEntity<>(shift, HttpStatus.OK);
}
}
Shift Class
@Entity
public class Shift {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "SHIFT_ID")
private Long id;
@Column(name = "START", nullable = false)
private OffsetDateTime start;
@Column(name = "END", nullable = false)
private OffsetDateTime end;
@ManyToOne(optional = false, fetch = FetchType.EAGER)
@JoinColumn(name = "USER_ID", nullable = false)
private User user;
@ManyToOne(optional = false, fetch = FetchType.EAGER)
@JoinColumn(name = "TASK_ID", nullable = false)
private Task task;
}
When running my test without debugging I get the following response (Body is NULL).
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[application/json;charset=UTF-8], X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Pragma=[no-cache], Expires=[0], X-Frame-Options=[DENY]}
Content type = application/json;charset=UTF-8
Body = null
Forwarded URL = null
Redirected URL = null
Cookies = []
When I add a breakpoint at the line Shift shift = shiftService.fetchOne(id);
in the ShiftController
,step-over, then resume, I get the response I want (Body Exists).
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[application/json;charset=UTF-8], X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Pragma=[no-cache], Expires=[0], X-Frame-Options=[DENY]}
Content type = application/json;charset=UTF-8
Body = {"id":2,"start":"2018-03-22T17:17:57.387-07:00","end":"2018-03-22T17:17:57.389-07:00","user":{"id":1,"username":"testuser","email":null,"role":"STUDENT"},"task":{"id":1,"name":"CLEANUP"}}
Forwarded URL = null
Redirected URL = null
Cookies = []
Some Googling leads me to believe that the issues stems from Hibernate's Lazy Loading. Whats the fix for this?
EDIT: Forgot to add that the shiftService.fetchOne()
method just wraps the JpaRepository's getOne()
method.
答案 0 :(得分:1)
This seems to be the culprit of your problem.
Forgot to add that the shiftService.fetchOne() method just wraps the JpaRepository's getOne() method.
The getOne method returns only the reference from DB (lazy loading). So basically you are outside of the transaction (the Transactional you have been declared in service class is not considered), and hence the slow response time in lazy loading.
Instead of getOne()
, you should use findOne()
JPA API in your shiftService.fetchOne()
implementation
Look at the API documentation here