blaze-persistence icon indicating copy to clipboard operation
blaze-persistence copied to clipboard

Query annotations for EntityViews in EntityViewRepository does not work

Open mj-p opened this issue 1 year ago • 3 comments

Hi, I was under the impression the @Query annotation would also work for EntityViews when using EntityViewRepository. When trying the following example while debugging the SQL statements I can see the I expected is executed and only containing the fields defined in my EntityView but then in the same Thread also another SQL is following which seems like default Hibernate Query. Followed by a ClassCastException from Node to NodeView. From the exception it seems there are 2 proxies chained for the forRoot() but I dont know if thats normal.

@Transactional(readOnly = true)
public interface NodeViewRepository extends EntityViewRepository<NodeView, Long> {

    @Query("SELECT n FROM Node n WHERE n.name = 'root'")
    NodeView findRoot();
}
java.lang.ClassCastException: class test.domain.jpa.Node cannot be cast to class test.api.blaze.view.node.NodeView (test.domain.jpa.Node and test.api.blaze.view.node.NodeView are in unnamed module of loader org.springframework.boot.loader.launch.LaunchedClassLoader @f6f4d33)
        at jdk.proxy2/jdk.proxy2.$Proxy310.findRoot(Unknown Source)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
        at java.base/java.lang.reflect.Method.invoke(Method.java:580)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
        at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:174)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:220)
        at jdk.proxy2/jdk.proxy2.$Proxy311.findRoot(Unknown Source)
        at test.api.blaze.service.NodeViewService.findRoot(NodeViewService.java:54)
        at test.api.blaze.controller.NodeViewController.findRoot(NodeViewController.java:64)

Also I am using @EnableJpaRepositories and @EnableBlazeRepositories together but scanning different packages if that matters.

Environment

version 1.6.11 integration-spring-data-3.1 Hibernate 6.4

mj-p avatar Feb 14 '24 15:02 mj-p

Hey, it is not possible to use the @Query annotation along with entity views. You will have to write that query with JPA Criteria e.g.

@Transactional(readOnly = true)
public interface NodeViewRepository extends EntityViewRepository<NodeView, Long> {

    default NodeView findRoot() {
        return findOne( ( root, query, cb ) -> cb.equal( root.get("name"), cb.literal("root") ) );
    }

    NodeView findOne(Specification<Node> spec);
}

beikov avatar Feb 15 '24 08:02 beikov

After digging a bit more through the issue it makes sense this wont work. Maybe the idea for our own Query annotation seems a bit overkill but should be doable I think? I'd like to hear your thoughts on what we would need and if that's even something interesting to have.

mj-p avatar Feb 17 '24 21:02 mj-p

It would be interesting, but that depends on https://github.com/Blazebit/blaze-persistence/issues/252 which is not so easy to implement. If https://github.com/jakartaee/persistence/issues/29 were already available, I could just reuse the parser of the JPA provider instead, but having to implement a custom parser requires a lot of work and integration with the parsers of the JPA providers is probably even more work.

beikov avatar Feb 19 '24 10:02 beikov