Search code examples
springjpajpqlspring-el

Can I refer a JPA entity within SpEL, on pageable findAll repository method


I have an entity

@Data
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name="component")
@Audited
public class Component implements Serializable {

    private static final long serialVersionUID = 0L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long Id;

    @Version
    private Long version;

    @Builder.Default
    private Boolean activated = true;

    private String name;


    @ManyToOne
    @JoinColumn(referencedColumnName="Id", nullable = true)
    @Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
    private Organisation organisation;

}

... and a repository interface:

@Repository
@RepositoryRestResource(exported = false)
public interface ComponentRepository extends JpaRepository<Component, Long>, JpaSpecificationExecutor<Component>, RevisionRepository<Component, Long, Integer> {


     @Query("select c from Component c where 1 = ?#{@authorisation.isInternalUser() or @authorisation.isUserInOrg(#c) ? 1:0}")
      Page<Component> findAll(@Nullable Specification<Component> spec, Pageable pageable);

}

My final goal is to filter out entities which the currently logged in user is not allowed to see, in an elegant way. I thought that the SpEL would be a nice way to do so, but I failed finding a way to pass the entity reference 'c' within the expression. Another alternative approach probably is to change the JPQL to something like this?

 @Query("select c from Component c where c.organisation = ?#{ @authorisation.getCurrentUserOrganisation()} or 1 = ?#{@authorisation.isInternalUser() ? 1:0}")

Or maybe there is a way to annotate directly the entity with some SpEL?

I tried to debug the Spring sources and understand how it works, but all I saw was that in the SpEL context evaluation ... there was access only to the Pageable object and the JPA Specification.

Thank you in advance!


Solution

  • Create Specification<Component> spec that do it:

    authorisation.isInternalUser() or @authorisation.isUserInOrg(#c) 
    

    And use it with

    Page<Component> findAll(@Nullable Specification<Component> spec, Pageable pageable);