1

I have two Entities. Parent and Child.

@Entity
public class Parent {

    @Id
    @Column(name = "PARENT_ID")
    private BigInteger id;

    @Column(name = "FIRST_NAME")
    private String firstName;

    @Column(name = "LAST_NAME")
    private String lastName;
}

@Entity
@NamedEntityGraph(name = "Child.parentObj", attributeNodes = @NamedAttributeNodes("parentObj"))
public class Child{
//blah blah blah

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="PARENT_ID")
Parent parentObj;

@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name="CHILD_ID")
Set<Address> address
//blah blah blah
}

ChildRepository.java

public interface ChildRepository extends JpaRepository<T, ID>, JpaSpecificationExecutor<T>{

     @EntityGraph(value="Child.parentObj")
     public List<Child> findAll(Specification<Child> spec);
}

I am trying to find child entities by criteria and it should always have parent.

I am getting exception that it is trying to find parentObj in Address table.

Caused by: org.hibernate.QueryException: could not resolve property: parentObj of: com.xxx.Address [..]

I found this link and tried solution given by Joep but same error.

Spring Data JPA + JpaSpecificationExecutor + EntityGraph

what am I missing. I am not able to understand why/how i limit to look for parentObj in just Child Object as Address has no reference to Parent.

I am doing search by Address.street.

I have tried ad-hoc entity graph too. exception:

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.QueryException: could not resolve property: parentObj of: com.xxx.Address 

Caused by: org.hibernate.QueryException: could not resolve property: parentObj of: com.xxx.Address
    at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:83)
    at org.hibernate.persister.entity.AbstractPropertyMapping.toType(AbstractPropertyMapping.java:77)
    at org.hibernate.persister.entity.AbstractEntityPersister.toType(AbstractEntityPersister.java:1978)
    at org.hibernate.hql.internal.ast.tree.FromElementType.getPropertyType(FromElementType.java:367)
    at org.hibernate.hql.internal.ast.tree.FromElement.getPropertyType(FromElement.java:500)
    at org.hibernate.engine.query.spi.EntityGraphQueryHint.getFromElements(EntityGraphQueryHint.java:95)
    at org.hibernate.engine.query.spi.EntityGraphQueryHint.toFromElements(EntityGraphQueryHint.java:68)
    at org.hibernate.hql.internal.ast.HqlSqlWalker.processQuery(HqlSqlWalker.java:676)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:665)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.collectionFunctionOrSubselect(HqlSqlBaseWalker.java:4905)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.comparisonExpr(HqlSqlBaseWalker.java:4606)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2104)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2029)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2029)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.whereClause(HqlSqlBaseWalker.java:796)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:597)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:301)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:249)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:278)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:206)
    ... 60 more
cp392
  • 31
  • 1
  • 9

2 Answers2

1

I wanted to find Child entries by criteria search and get ParentObj for each child. I wanted to do join and not individual select for Parent. I was trying to solve that by using EntityGraph but it didn't work. As @EKlavya pointed out Specification and EntityGraph don't work togather.

The way I solved was:

root.fetch("parentObj", JOIN.LEFT);

in my toPredicate method. this will get Child entity with Parent in 1 query.

cp392
  • 31
  • 1
  • 9
0

You are using Child.parentObj as Entity graph name but you named the entity graph as Child.parent. Use

@EntityGraph(value="Child.parent")

Without @NamedEntityGraph

we can define an ad-hoc entity graph, without @NamedEntityGraph just use

@EntityGraph(attributePaths = {"parentObj"})

Update: Entity graph and specification both are not working together. There is a way to solve this. Don't do eager for parent fetch child only first then make a list of child ids from child's and get parents using in clause query using child ids. Total only 2 queries needed. If you want to solve this using 1 query use DSL to do raw query.

Eklavya
  • 17,618
  • 4
  • 28
  • 57
  • There was typing error for parentOBj. I have fixed it. I have tried ad-hoc entity graph as well. I am not able to understand why/how i limit to look for parentObj in just Child Object as Address has no reference to Parent. – cp392 Apr 17 '20 at 12:21
  • Similer error. stacktrace is diferent. but it is looking for parentObj in Address.I started with ad-hoc entity graph and then moved to NamedEntityGraph in hope for solution. – cp392 Apr 17 '20 at 12:44
  • Can you add detail stacktrace for adhoc graph also – Eklavya Apr 17 '20 at 12:45
  • updated original post with details. thanks for help and time. – cp392 Apr 17 '20 at 12:54
  • Add full stacktrace(not just 1 line) and Parent entity class also – Eklavya Apr 17 '20 at 12:57
  • added more details. – cp392 Apr 17 '20 at 14:22
  • Oh ! I didn't see that you are using the specification, Entity graph and specification both are not working together. Sorry bro – Eklavya Apr 17 '20 at 14:31
  • IS it a fact? I didn't find any examples so I going to trust you. So can you suggest to tackle this problem any other way. I mean use Specification on Child table bcs I have bunch properties on Child that I can serach by and result should be join of Child and Parent. Initally I was not going for join and relying on individual queries done by jpa to populate Child but as moved to more testing I realised that if I get 50 child objects then there will be 50 select for parent. I want to avoid that. – cp392 Apr 17 '20 at 14:47
  • You can fetch child first then make a list of child ids and get parent using in query. Currently I don't get any better way – Eklavya Apr 17 '20 at 15:03
  • If I don't do entity graph, it used to find all Child entries and then each Parent bcs of FetchType.EAGER. But that is very expensive as I may find lot of Child entiries and that means it will perform that many select on Parent table. I dont want that. – cp392 Apr 17 '20 at 17:20
  • Don't do eager for parent fetch child only first then make a list of child ids from child's and get parent using in clause query using child ids. Only 2 query – Eklavya Apr 17 '20 at 17:23
  • Yes, but I am trying to do with 1. I am updating old code to spring and it does with 1 query so anything more than 1 query is kind of defeating the purpose of upgrade. – cp392 Apr 17 '20 at 17:29
  • Then use DSL query (raw) then it is possible – Eklavya Apr 17 '20 at 17:37
  • thanks. i am going to keep this question open to see someone else has any other ideas. – cp392 Apr 18 '20 at 14:47
  • The 2 query idea is not that great. If the first query selects too much ids, it may explode the cost of the second query if it makes a WHERE id IN (ids-selected-in-first-query) – AndD Mar 12 '21 at 11:13