简体   繁体   中英

How can I use QueryDSL on multiple mongo repositories?

I am building a profile service with the typical REST endpoints for creating, reading, updating and deleting profiles. For this I am using the Spring Framework together with a MongoDB. On top I would like to use QueryDSL to create some custom queries.

A full minimal working example of the current implementation can be found here: https://github.com/mirrom/profile-modules

I would like to have sub profile models that extend the base profile model, and sub sub models that extend the sub models. By this I have hierarchical profiles that inherit the fields of its parent profile. The idea is to store all profiles in the same collection and distinguish them via the automatically created _class field.

A simple example (with Lombok annotations):

@Data
@Document(collection = "profiles")
@Entity
public class Profile {
    
    @Id
    private ObjectId id;
    
    @Indexed
    private String title;
    
    @Indexed
    private String description;
    
    private LocalDateTime createdAt;
    
    private LocalDateTime modifiedAt;
    
}
@Data
@Entity
@EqualsAndHashCode(callSuper = true)
public class Sub1Profile extends Profile {
    
    private String sub1String;
    
    private int sub1Integer;
    
}

While (all) profiles can get accessed via the endpoint /api/v1/profiles , the sub1Profiles can be accessed via /api/v1/profiles/sub-1-profiles . Currently the sub1Profiles endpoint delivers all profiles, but it should just deliver the sub1Profiles and its children. For this I would like to use QueryDSL, but I can't add QuerydslPredicateExecutor<Profile> and QuerydslBinderCustomizer<QProfile> to more than one repository interface. This is how my profile repository looks like:

@Repository
public interface ProfileRepository extends MongoRepository<Profile, ObjectId>, QuerydslPredicateExecutor<Profile>,
        QuerydslBinderCustomizer<QProfile> {
    
    @Override
    default void customize(QuerydslBindings bindings, QProfile root) {
        
        bindings.bind(String.class)
                .first((SingleValueBinding<StringPath, String>) StringExpression::containsIgnoreCase);
    }
    
}

If I now try to do the same with Sub1ProfileRepository:

@Repository
public interface Sub1ProfileRepository
        extends MongoRepository<Sub1Profile, ObjectId>, QuerydslPredicateExecutor<Sub1Profile>,
        QuerydslBinderCustomizer<QSub1Profile> {
    
    default void customize(QuerydslBindings bindings, QProfile root) {
        
        bindings.bind(String.class)
                .first((SingleValueBinding<StringPath, String>) StringExpression::containsIgnoreCase);
    }
    
}

I get this error message:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sub1ProfileRepository' defined in com.example.profile.repository.sub1profile.Sub1ProfileRepository defined in @EnableMongoRepositories declared on MongoRepositoriesRegistrar.EnableMongoRepositoriesConfiguration: Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property customize found for type Sub1Profile!

What am I missing?

In Sub1ProfileRepository 's customize method, you have used QProfile as method argument. Can you use QSub1Profile instead and check if it's working?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM