views:

681

answers:

1

I have an entity class and a subclass based on that entity:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class A

and

@Entity
public class B extends A

I need to issue a native query that uses a stored procedure on the base class (A) only. If I attempt it as follows:

entityManager.createNativeQuery("select * from A a where procedure(f)",A.class).getResultList()

I get an error regarding "The column clazz_ was not found in the ResultSet". I assume that the JPA provider adds this column in order to discriminate between the base class and the extended class. I can work around this problem by explicitly adding the clazz column and all of the fields from the subclass:

entityManager.createNativeQuery("select *,1 as clazz_,null as prop1,null as prop2 from A a where procedure(f)",A.class).getResultList()

where "prop1" and "prop2" are properties of the subclass B. However, this seems like an unnecessary hack and is prone to maintenance problems if the subclass B changes.

My question is: How can I query using a stored procedure on an entity that has inheritance defined on it?

+2  A: 

As you've probably seen, the Hibernate team hasn't put a lot of work into defining how you do this.. the documentation simply states:

16.1.6. Handling inheritance

Native SQL queries which query for entities that are mapped as part of an inheritance must include all properties for the baseclass and all its subclasses.

So if you want to use Native queries it looks like you're stuck doing something like this. Regarding the concern about the subclass B changing, perhaps a slightly less onerous way of implementing this would be to try using LEFT OUTER JOIN syntax on the shared ID property:

entityManager.createNativeQuery("select a.*, b*, 1 as clazz_, from A a LEFT OUTER JOIN B b on id = a.id where procedure(f)",A.class).getResultList()

That way you'll always get all of the properties from B if you add or remove some.

BryanD
So, I had thought of this, but the problem is that when Hibernate attempts to inflate the object from the ResultSet row, it finds two id columns, one of which is null. I suppose I can add an additional where clause the filters out 'b.id is null'.
algoriffic