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
юридические лица?