Search code examples
inheritancejpanamed-query

JPA: TypedQuery gets no results for inherited types


I have an entity which extends another entity:

@Entity
@DiscriminatorValue("PARKING")
@Table(name="parkingPois")
@NamedQueries({
    @NamedQuery(name="ParkingPoiDao.findAll", query="SELECT p FROM ParkingPoiDao p"), 
    @NamedQuery(name="ParkingPoiDao.findById", query="SELECT p FROM ParkingPoiDao p WHERE p.parkingPoiId = :parkingPoiId")
})
public class ParkingPoiDao extends PoiDao implements Serializable {
    //@Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id")
    private int id;
    @Column(name="parkingPoiId")
    private String parkingPoiId;
    @Column(name="poiId")
    ...
}

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="poiType", discriminatorType=DiscriminatorType.STRING)
@Table(name="pois")
public abstract class PoiDao implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="poiId")
    private int poiId;
...

When I try to query for a parkingPoi I get nor results.

        TypedQuery<ParkingPoiDao> query =
                em.createNamedQuery("ParkingPoiDao.findAll", ParkingPoiDao.class);
//      TypedQuery<ParkingPoiDao> query =
//              em.createNamedQuery("ParkingPoiDao.findById", ParkingPoiDao.class)
//              .setParameter("parkingPoiId", facilityId);
//              .setParameter("poiType", "ParkingPOI");
//      ParkingPoiDao pPoiDao = query.getSingleResult();
        List<ParkingPoiDao> pPoiDaos = query.getResultList();

(Both, the active and the outcommented queries have no results.)

In the database I have a table pois for the parent class and a "subtable" for parkingPois which holds a foreign key (pois.poiId).

What can be the reason??


Solution

  • I am implementing joined, multiple table inheritance. Joined inheritance is the most logical inheritance solution because it mirrors the object model in the data model. In joined inheritance a table is defined for each class in the inheritance hierarchy to store only the local attributes of that class. Each table in the hierarchy must also store the object's id (primary key), which is only defined in the root class. All classes in the hierarchy must share the same id attribute. A discriminator column is used to determine which class the particular row belongs to, each class in the hierarchy defines its own unique discriminator value.

    The problem was that I had to add @ObjectTypeConverter annotation on class level as well as @Convert annotation on field level:

    @ObjectTypeConverters({
        @ObjectTypeConverter (
                name="poiTypeConverter",
                dataType=java.lang.String.class,
                objectType=ServiceTypeEnum.class,
                conversionValues={
                    @ConversionValue(dataValue="CHARGING", objectValue="CHARGING"),
                    @ConversionValue(dataValue="PARKING", objectValue="PARKING")
                }
        )
    @Entity
    @Inheritance(strategy=InheritanceType.JOINED)
    @DiscriminatorColumn(name="poiType", discriminatorType=DiscriminatorType.STRING)
    @Table(name="pois")
    public abstract class PoiDao implements Serializable {
        private static final long serialVersionUID = 1L;
    
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name="poiId")
        private int poiId;
        @Convert("poiTypeConverter")
        private ServiceTypeEnum poiType;
    ...
    
    @Entity
    @DiscriminatorValue("PARKING")
    @Table(name="parkingPois")
    @NamedQueries({
        @NamedQuery(name="ParkingPoiDao.findAll", query="SELECT p FROM ParkingPoiDao p"), 
        @NamedQuery(name="ParkingPoiDao.findById", query="SELECT p FROM ParkingPoiDao p WHERE p.parkingPoiId = :parkingPoiId")
    })
    public class ParkingPoiDao extends PoiDao implements Serializable {
        //@Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name="id")
        private int id;
        @Column(name="parkingPoiId")
        private String parkingPoiId;
        @Column(name="poiId")
        @Convert("parkingPoiStatusConverter")
        @Column(name="status")
        private ParkingPoiStatusEnum status;
        ...
    }
    

    Of course, the respective values must be in the database if records are already in the table(s).