0


We have an inheritance hierarchy say like this:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@NamedQuery("select NEW package.BaseClass(bc.field1, bc.field2) from BaseClass b")
public abstract BaseClass {
   public BaseClass(int field1, String field2) {
   }
}

@Entity
public SubClass1 extends BaseClass {
}

and similarly SubClass2

Now the problem I face is with the @NamedQuery syntax here, which does not allow me to create List objects because it cannot instantiate BaseClass using constructor. So can anyone suggest how to solve this while leaving the named query in base class itself?

Or please tell me if there is a way to exclude a column in the select as in

select bc.*Field3 from BaseClass

or some syntax like that prevents the lazy loading of association field3 that I don't need in this case?

Predrag Maric
  • 23,938
  • 5
  • 52
  • 68
Paddy
  • 3,472
  • 5
  • 29
  • 48
  • Since the collection is **lazy** loaded, executing a query won't load it. Just use select b from BaseClass b. – JB Nizet Sep 02 '15 at 08:01
  • @JBNizet, first of all, a small correction and I have updated the question, it is not a collection that I want to avoid, but an association. But it did fire in the query for the lazy loaded association even without an access to this association object. Confirmed that just now. Unfortunately I am not sure if I can post my code-related info here otherwise I can show the proof in the form of the query fired. I am using JOIN FETCH for another association object in the parent object but the unwanted query seems to be for another association object, not the one for which I am using JOIN FETCH. – Paddy Sep 02 '15 at 08:58

1 Answers1

1

You are using some things here in a strange way.

First, JPQL constructor expressions are normally used with non-entity classes. You can have some non-entity class with two fields (field1 and field2) and a matching constructor and use that in place of package.BaseClass in your @NamedQuery, and it should work. I don't see a point in using an entity class here. If you expected to get a list of BaseClass entities with only field1 and field2 initialized, that's just not how it works. But select bc.field1, bc.field2 from BaseClass b will work, but it will give a tuple as a result, not entities.

Also, @OneToOne and @ManyToOne are by default eagerly fetched, so that might be the reason for additional query firing that you see. Set it explicitly to be FetchType.LAZY and it should be ok.

Regarding this

how to solve this while leaving the named query in base class itself

you don't have to keep the named query in the base class, you can put it in whatever entity you want. An often used option is to have one "fake" entity that will hold all named queries at one place. Check out this answer for an example.

Community
  • 1
  • 1
Predrag Maric
  • 23,938
  • 5
  • 52
  • 68
  • With my application I am not sure if putting FetchType.LAZY is avoiding the firing of the query as I do see the query but let me assume it occurs due to other reasons specific to my application. Now my question is can I make this FetchType.LAZY specific to the query in question rather than putting it in the annotation? Hibernate is my JPA provider. – Paddy Sep 02 '15 at 10:14
  • I'm not sure you can override eager association to lazy on a query level, at least I don't know how. Maybe the best option is to create a non-entity class with only the fields you need, and use that in constructor expression (if it fits the rest of your code, of course). – Predrag Maric Sep 02 '15 at 10:54