بالدرس السابق وصلنا الـ Department بالـ Employee. اليوم رح نضيف Leave Request - طلبات الإجازات - ونربطها بالـ Employee.
العلاقة بين Employee والـ Leave Request هي One-to-Many من جهة الـ Employee:
@Entity
@Table(name = "leave_request")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class LeaveRequest {
@Id
@GeneratedValue
@UuidGenerator
private UUID id;
@Column(name = "start_date", nullable = false)
private
اشترك في النشرة البريدية
دروس جديدة، مقالات، وأدوات مباشرة لبريدك.
@ManyToOne - يعني كثير Leave Requests لـ Employee واحد. اقرأها: "Many (LeaveRequest) to One (Employee)"FetchType.LAZY - ما يجيب بيانات الـ Employee إلا لما تحتاجها فعلاً (أفضل لأداء)@JoinColumn(name = "employee_id") - اسم عمود الـ Foreign Key بالجدولHibernate تلقائياً ينشئ الـ Table وال Foreign Key Constraint بين leave_request وemployee.
public record LeaveRequestCreate(
@NotNull LocalDate startDate,
@NotNull LocalDate endDate,
@NotBlank(message = "Reason is required") String reason
) {}ما نحتاج employeeId بالـ DTO لأنو رح نأخذه من الـ URL.
الـ JpaRepository بالأساس بيعطيك findById وfindAll، بس ما فيه findByEmployeeId. الحل هو تعريف Method بالـ Interface باسم خاص:
@Repository
public interface LeaveRequestRepository extends JpaRepository<LeaveRequest, UUID> {
List<LeaveRequest> findAllByEmployeeId(UUID employeeId);
}Hibernate بيقرأ اسم الـ Method تلقائياً ويولّد الـ SQL المناسب:
SELECT * FROM leave_request WHERE employee_id = ?المهم إنو الاسم يطابق اسم الـ Field بالـ Entity - employee_id يصير findAllByEmployee_Id أو اختصاراً findAllByEmployeeId.
public interface LeaveRequestService {
LeaveRequest create(UUID employeeId, LeaveRequestCreate dto);
List<LeaveRequest> findAllByEmployeeId(UUID employeeId);
}@Service
public class LeaveRequestServiceImpl implements LeaveRequestService {
@Autowired
private LeaveRequestRepository leaveRequestRepository;
@Autowired
private EmployeeService employeeService;
@Override
public LeaveRequest create(UUID employeeId, LeaveRequestCreate dto) {
Employee employee = employeeService.findOne(employeeId);
LeaveRequest request = new LeaveRequest();
request.setEmployee(employee);
request.setStartDate(dto.startDate());
request.setEndDate(dto.endDate());
request.setReason(dto.reason());
request.setStatus("PENDING");
return leaveRequestRepository.save(request);
}
@Override
public List<LeaveRequest> findAllByEmployeeId(UUID employeeId) {
return leaveRequestRepository.findAllByEmployeeId(employeeId);
}
}بنضيف Leave Request Endpoints جوا الـ Employee Controller:
// POST /employees/{employeeId}/leave-requests
@PostMapping("/{employeeId}/leave-requests")
public ResponseEntity<GlobalResponse<LeaveRequest>> createLeaveRequest(
@PathVariable UUID employeeId,
@Valid @RequestBody LeaveRequestCreate dto) {
var created = leaveRequestService.create(employeeId, dto);
return new ResponseEntity<>(new GlobalResponse<>(created), HttpStatus.CREATED);
}
// GET /employees/{employeeId}/leave-requests
@GetMapping("/{employeeId}/leave-requests")
public ResponseEntity<GlobalResponse<List<LeaveRequest>>> getLeaveRequests(
@PathVariable UUID employeeId) {
var requests = leaveRequestService.findAllByEmployeeId(employeeId);
return new ResponseEntity<>(new GlobalResponse<>(requests), HttpStatus.OK);
}لإنشاء طلب إجازة:
POST /employees/{employeeId}/leave-requests
{
"startDate": "2024-07-01",
"endDate": "2024-07-07",
"reason": "Summer vacation"
}
ولجلب كل طلبات موظف معين:
GET /employees/{employeeId}/leave-requests
رح يرجع كل الـ Leave Requests التابعة لهاد الـ Employee ID.
بالدرس الجاي رح ننتقل على Spring Security ونضيف User Accounts مع Sign Up وSign In.