JPA: TypedQuery не получает результатов для унаследованных типов

У меня есть сущность, которая расширяет другую сущность:

@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;
...

Когда я пытаюсь запросить парковку, я не получаю ни результатов.

        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();

(И активный, и закомментированный запросы не имеют результатов.)

В базе данных у меня есть таблица pois для родительского класса и "subtable" для parkingPois, который содержит внешний ключ (pois.poiId).

В чем может быть причина??

2 ответа

Решение

Я реализую объединенное наследование нескольких таблиц. Объединенное наследование является наиболее логичным решением наследования, поскольку оно отражает объектную модель в модели данных. В объединенном наследовании для каждого класса в иерархии наследования определяется таблица, в которой хранятся только локальные атрибуты этого класса. Каждая таблица в иерархии также должна хранить идентификатор объекта (первичный ключ), который определен только в корневом классе. Все классы в иерархии должны иметь один и тот же атрибут id. Столбец дискриминатора используется для определения того, к какому классу принадлежит конкретная строка, каждый класс в иерархии определяет свое собственное уникальное значение дискриминатора.

Проблема заключалась в том, что мне пришлось добавить аннотацию @ObjectTypeConverter на уровне класса, а также аннотацию @Convert на уровне поля:

@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;
    ...
}

Конечно, соответствующие значения должны быть в базе данных, если записи уже находятся в таблице (ах).

Я должен был добавить parkingPoiId собственность на ваш ParkingPoiDaoюридическое лицо, так что ParkingPoiDao.findById Именованный запрос был действительным:

@Entity
@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 {

    private String parkingPoiId;

    public String getParkingPoiId() {
        return parkingPoiId;
    }

    public void setParkingPoiId(final String parkingPoiId) {
        this.parkingPoiId = parkingPoiId;
    }
}

Таким образом, после добавления следующего теста пройдем оба ваших запроса:

@Test
@Transactional
public void return_parking_pois() {
    ParkingPoiDao parkingPoi = new ParkingPoiDao();
    parkingPoi.setParkingPoiId("123");
    em.persist(parkingPoi);

    TypedQuery<ParkingPoiDao> query = em
            .createNamedQuery("ParkingPoiDao.findById", ParkingPoiDao.class)
            .setParameter("parkingPoiId", "123");
    List<ParkingPoiDao> pPoiDaos = query.getResultList();

    assertThat(pPoiDaos).hasSize(1);

    query = em.createNamedQuery("ParkingPoiDao.findAll", ParkingPoiDao.class);
    pPoiDaos = query.getResultList();

    assertThat(pPoiDaos).hasSize(1);
}

Не могли бы вы подтвердить, в чем разница с вашими сущностями, и, возможно, добавить детали того, как вы сохраняете ParkingPoiDao юридические лица?

Другие вопросы по тегам