Spring data JPA using Entity Type expression

2019-07-16 01:30发布

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条回答
淡お忘
2楼-- · 2019-07-16 01:53

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.

查看更多
【Aperson】
3楼-- · 2019-07-16 01:58

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.

查看更多
登录 后发表回答