Skip to content

Instantly share code, notes, and snippets.

@regispires
Last active November 15, 2025 20:49
Show Gist options
  • Select an option

  • Save regispires/3fb816ce56eb4e3b2543f556df4c38d0 to your computer and use it in GitHub Desktop.

Select an option

Save regispires/3fb816ce56eb4e3b2543f556df4c38d0 to your computer and use it in GitHub Desktop.
BaseCrudController
package com.example.api;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
public abstract class BaseCrudController<T> {
// Each concrete controller must provide its own repository
protected abstract JpaRepository<T, Integer> getRepository();
// LIST (pagination + sorting)
@GetMapping
public Page<T> list(Pageable pageable) {
return getRepository().findAll(pageable);
}
// FIND BY ID
@GetMapping("/{id}")
public ResponseEntity<T> findById(@PathVariable Integer id) {
return getRepository().findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
// CREATE
@PostMapping
public ResponseEntity<T> create(@RequestBody T entity) {
T saved = getRepository().save(entity);
return ResponseEntity.status(HttpStatus.CREATED).body(saved);
}
// UPDATE
@PutMapping("/{id}")
public ResponseEntity<T> update(@PathVariable Integer id, @RequestBody T entity) {
if (!getRepository().existsById(id)) {
return ResponseEntity.notFound().build();
}
T saved = getRepository().save(entity);
return ResponseEntity.ok(saved);
}
// DELETE
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Integer id) {
if (!getRepository().existsById(id)) {
return ResponseEntity.notFound().build();
}
getRepository().deleteById(id);
return ResponseEntity.noContent().build();
}
}
@RestController
@RequestMapping("/api/participations")
public class ParticipationController extends BaseCrudController<Participation> {
private final ParticipationRepository participationRepository;
public ParticipationController(ParticipationRepository participationRepository) {
this.participationRepository = participationRepository;
}
@Override
protected JpaRepository<Participation, Integer> getRepository() {
return participationRepository;
}
@GetMapping("/by-student/{id}")
public List<Participation> byStudent(@PathVariable Integer id) {
return participationRepository.findByStudentId(id);
}
}
package com.example.repository;
import com.example.model.Participation;
import com.example.model.Status;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface ParticipationRepository extends JpaRepository<Participation, Integer> {
// Derived Query Method
List<Participation> findByStudentId(Integer studentId);
List<Participation> findByProjectId(Integer projectId);
List<Participation> findByStatus(Status status);
// Custom JPQL query
@Query("select p from Participation p where p.student.id = :studentId and p.status = :status")
List<Participation> findByStudentAndStatus(
@Param("studentId") Integer studentId,
@Param("status") Status status
);
// Query with sorting inside
List<Participation> findByStudentIdOrderByCreatedAtDesc(Integer studentId);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment