0

I am trying to make a recursive query using blaze persistence lib.

I have two tables (a and a_temp) and entities (A and ATemp respectively) that represent them. ATemp is almost like an entity view to the A class, but its table serves to temporary persist A object in data base (it's done by someone else and I don't intend on changing this). So, A and ATemp share some common columns. I also have an ACte.class, which is CTE of A.class.

I'm trying to join them by some of their properties, but get the following error:

Attribute 't' not found on type 'A'; nested exception is java.lang.IllegalArgumentException: Attribute 't' not found on type 'A'

the Criteria Builder looks like this

CriteriaBuilder<A> cb = cbf.create(em, A.class)
             .from(A.class, "s")

             .innerJoinOn(ATemp.class, "t")
                    .onExpression("s.prop1.id = t.prop1.id"
                                + " AND s.prop2 = t.prop2")
             .end()

             // ...some more joins...
             
             .whereExpression("...")
             .where("s.id").notIn()

                   .from(ACte.class, "r")
                   .withRecursive(ACte.class)
                        .from(A.class, "m")
                        // bindings
                        .whereExpression("m.id = t.somepropId")

                   .unionAll()

                        .from(ACte.class, "r")
                        // bindings
                        .innerJoin(A.class, "d")
                              .onExpression("d.id = r.somepropId")
                        .end()

                        .end()

                   .select("r.id")
                   .end()

             .select("s");

then I simply do cb.getResultList() and after I call for the method I get the error above.

What could possibly be wrong with it? I don't really get why it counts 't' as A class field and not an alias for ATemp

Thanks for any advice!

Upd.: for better clarity I decided to post a structure of the A and ATemp entities

@Entity
@Table(name = "a")
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class A extends SomeParentClassThatHasId {

    @Column(name = "prop1")
    @Getter
    @Setter
    private SomeInnerClass prop1;

    @Column(name = "prop2")
    @Getter
    @Setter
    private String prop2;

    ...

}
@Entity
@Table(name = "a_temp")
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ATemp extends SomeParentClassThatHasId {

    @Column(name = "prop1")
    @Getter
    @Setter
    private SomeInnerClass prop1;

    @Column(name = "prop2")
    @Getter
    @Setter
    private String prop2;

    ...

}
@CTE
@Entity
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ACte extends SomeParentClassThatHasId {

    private Long somepropId;

    ...
}

1 Answers1

0

It's hard to say for sure what is happening (I might need to see a reproducer for this), but it seems to me that the use of .whereExpression("m.id = t.somepropId") might be the cause for this.

You are trying to add a recursive CTE from within a subquery, but it is not possible to refer to aliases in such CTEs. CTEs are fully isolated. I don't know what your use case is, but if you need some help with that, join the community on Slack where we can dive deeper into this.

I think though, that you should try to write your CTE first, and then try to join against that.

Christian Beikov
  • 15,141
  • 2
  • 32
  • 58
  • Thank you for the answer, Cristian! It was also my first guess about problem being at `.whereExpression("m.id = t.somepropId")`, but I still don't know how to work around it. Problem is that I already have this native query that I need to re-do using anything that supports recursive queries to make it non-native, and so I can't really change the logic behind it. I'll try and see if I can change something inside the query itself, maybe that'll help. I tried writing my CTE first, and then joining against it, but it couldn't refer to that misterious 't'. So the problem stays :) – arslandinho Apr 21 '22 at 11:48
  • You can put add a column for `m.id` to the CTE and join against the CTE. – Christian Beikov Apr 21 '22 at 13:19