#inheritance #jpa #named-query
#наследование #jpa #именованный запрос
Вопрос:
У меня есть объект, который расширяет другой объект:
@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;
...
Когда я пытаюсь запросить parkingPoi, я не получаю никаких результатов.
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();
(Как активные, так и удаленные запросы не дают результатов.)
В базе данных у меня есть таблица poi для родительского класса и «подтаблица» для parkingPois, которая содержит внешний ключ (pois.poiId).
В чем может быть причина??
Комментарии:
1. Вы пробовали выполнить сгенерированный запрос в базе данных, чтобы узнать, есть ли у какого-либо запроса какие-либо результаты?
Ответ №1:
Мне пришлось добавить 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
сущности?
Комментарии:
1. У меня уже есть собственность parkingPoiId в ParkingPoiDao. Я думаю, что проблема основана на том факте, что столбец poiType (который является столбцом дискриминатора) в PoiDao является перечислением !??
2. Я не уверен, что понимаю вас.
discriminatorType
Принимает ajavax.persistence.DiscriminatorType
(который является перечислением), но это сделано специально. Если это все еще не работает, возможно, вы можете разместить пример проекта на GitHub или что-то, на что можно взглянуть?
Ответ №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;
...
}
Конечно, соответствующие значения должны быть в базе данных, если записи уже есть в таблице (таблицах).