2

I would like to use the JPA 2.0 Type expression in a spring data JPA repository @Query but it give me a validation error Validation failed for query for method public abstract java.util.List my.org.FooRepository.findAllByRoomCode()!.

Here is my entities definition :

inherited :

@Entity(name = "Location")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class LocationEntity {

    @Column(name = "CODE")
    protected String code;

    @OneToMany(mappedBy = "location")
    protected List<LampEntity> lamps = new ArrayList<LampEntity>();
        ...
}

@Entity(name = "Floor")
@Table(name = "FLOOR", uniqueConstraints = {
    @UniqueConstraint(name = "FLOOR_UK", columnNames = "CODE")
})
public class FloorEntity extends LocationEntity {
    ...
    @OneToMany(mappedBy = "floor")
    private List<RoomEntity> rooms = new ArrayList<RoomEntity>();
    ...
}

@Entity(name = "Room")
@Table(name = "ROOM", uniqueConstraints = {
    @UniqueConstraint(name = "ROOM_UK", columnNames = { "CODE", "FLOOR_ID" })
})
public class RoomEntity extends LocationEntity {
    ...
    @ManyToOne
    @JoinColumn(name = "FLOOR_ID", nullable = false, referencedColumnName = "ID")
    private FloorEntity floor;
    ...
}

requested entity :

@Entity(name = "Lamp")
@Table(name = "LAMP")
public class LampEntity {

    @ManyToOne
    @JoinColumn(name = "LOCATION_ID", referencedColumnName = "ID")
    private LocationEntity location;
}

repository :

public interface LampRepository extends JpaRepository<LampEntity, Long> {

    @Query("SELECT lamp FROM Lamp lamp WHERE lamp.location.code = :locationCode AND TYPE(lamp.location) = Room")
    public List<LampEntity> findAllByRoomCode(@Param("code") String locationCode);
    ...
}

I'm using spring-data-JPA 1.4.1.RELEASE with Hibernate 4.2.7.Final as provider.

My questions are :

  1. Is it possible to do that with Spring data JPA ?
  2. In a old stackoverflow post i saw that Hibernate accepted it only with InheritanceType.SINGLE_TABLE but maybe now it's ok in 4.2.7 ?
  3. If not, what are my alternative if I want to keep my InheritanceType.TABLE_PER_CLASS strategy ?

Thanks a lot


Updated with unique constraints and relation between Floor and Room

2
  • Any chance you post the complete stace trace you see? Commented Jul 8, 2014 at 15:05
  • It's OK, I've found the problem and it isn't Spring data JPA fault ;), it belongs to Hibernate. I can't post my analysis for now (less than 10 reputation), I'll post it in a couple of hours Commented Jul 8, 2014 at 15:38

2 Answers 2

1

If you use Spring JPA repository, you can do this without @Query by renaming the method as:

public List<LampEntity> findByLocation_Code(@Param("code") String locationCode);

Just make sure all your setters and getters are in place.

Sign up to request clarification or add additional context in comments.

3 Comments

Yes, but in this case I would have an incorrect result. Indeed, my code unique constraints are relative to the concrete implementations and not to the abstract class. I can have a Floor and a Room with same code.
is there also a type field in Location table.
No. There is neither type field nor @DiscriminatorColumn on Location Entity. By the way, Location is only an abstract Entity and there isn't no table for it
1

OK, my mistake, I have misunderstood a couple of things and not read fully the stacktrace :

  1. The error doesn't belong to Spring Data but to Hibernate. The real Caused by is org.hibernate.QueryException: could not resolve property: class of: xxx.yyy.LampEntity [SELECT lamp FROM xxx.yyy.LampEntity lamp WHERE lamp.location.code = :locationCode AND TYPE(lamp.location) = Room]
  2. As the property class is clearly named here, I ran a couple of tests of validity (the requests below are totally functionnaly incorrect, it's just for the syntax) :

@Query("SELECT lamp FROM Lamp lamp WHERE lamp.location.code = :code AND TYPE(lamp) = Lamp") fails, same stacktrace

@Query("SELECT lamp FROM Lamp lamp WHERE lamp.location.code = :code AND lamp.location.class = Room") OK, works correctly, the expected results are returned (only the lamps which have a room's location)

I Created a new Repository public interface LocationRepository extends JpaRepository<LocationEntity, Long> and I tested :

@Query("SELECT location FROM Location location WHERE TYPE(location) = Room AND location.code = :code") OK, works correctly.

So I'll go with the lamp.location.class (Hibernate specific :() because it seems Hibernate (or JPA ?) doesn't allow to TYPE nor an attribute in an HQL request, neither an entity which is not inherited (pretty logic this one).

Please let me know if there is any complement or correction to this answer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.