I am currently wondering whether a particular use case could be elegantly addressed by using a default interface method inside a JPA repository.
Suppose we have the following entity and supporting types:
public enum Status {
STATUS_1,
STATUS_2,
STATUS_3
}
@Entity
@Getter // from lombok
@Setter // from lombok
public class SomeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "status")
private Status status;
}
I need to be able to query a list of SomeEntity
based on combination of Status
enumeration values.
With Spring JPA, its respective repository could look like this:
@Repository
public interface SomeRepository extends JpaRepository<SomeEntity, Integer> {
@Query("select s.id, ... from SomeEntity s where s.status in (:statuses)")
List<SomeEntity> getByStatuses(@Param("statuses") List<Status> statuses);
}
The particular combinations of statuses that must be passed, however is very much dependent on the domain of SomeEntity
, and I'd like to "bake-in" those statuses in the repository call. Why in the repository -- currently the same repository is used from multiple services, and SomeEntity
is updated as part of transactions dealing with other entities updated together according to the service's specifics. The particular getByStatuses
calls are the same for all services, and we have duplicated code fragments looking roughly like this:
List<Status> statuses = Arrays.asList(Status.STATUS_1, Status.STATUS_3);
List<SomeEntity> entities = someRepository.getByStatuses(statueses);
....
I was wondering if I could extract the above fragment in a default method inside the repository and change my services to use that method instead:
@Repository
public interface SomeRepository extends JpaRepository<SomeEntity, Integer> {
@Query("select s.id, ... from SomeEntity s where s.status in (:statuses)")
List<SomeEntity> getByStatuses(@Param("statuses") List<Status> statuses);
default List<SomeEntity> getByRelevantStatuses() {
List<Status> relevantStatuses = Arrays.asList(Status.STATUS_1, Status.STATUS_3);
return this.getByStatuses(relevantStatuses);
}
}
My concerns are the "magic" behind the scenes which Spring will do, could it cause issues with an approach like the above?
It appears that the default interface method usage in the described scenario is working. I tried it and so far I have not seen any problems.
I'll still be happy to know if there are things to worry about, and if I find anything useful myself, I will update this post.