#java #spring-boot #hibernate #entity #hibernate-criteria
Вопрос:
У меня есть рабочее приложение с 30 объектами или около того. В основном используется репозиторий CRUD, который автоматически генерирует запросы. Теперь некоторые запросы не оптимизированы, и я хочу использовать систему диаграмм сущностей для объединения таблиц для некоторых из них.
Пока все шло хорошо, я последовал нескольким учебникам и написал код. Единственная оставшаяся проблема заключается в том, что при запуске я получаю эту ошибку:
Not an entity: class com.stingray.syncmanager.models.StationRoleModel
Это очень странно, потому что, как я уже говорил ранее, мое приложение уже использует эту сущность. Мне кажется, что менеджер сущностей или сеанс «не осознают», что эти сущности существуют, например, если бы они находились в отдельном «контексте», если это имеет смысл.
Кто-нибудь может указать мне правильное направление? Вот мой код:
CustomSqlRepository.java
public CustomSqlRepository(HibernateConfig hibernateConfig, EntityManager entityManager) {
Map<String, String> settings = new HashMap<>();
settings.put("connection.driver_class", hibernateConfig.getDriverClassName());
settings.put("hibernate.connection.url", hibernateConfig.getConnectionUrl());
settings.put("hibernate.connection.username", hibernateConfig.getUsername());
settings.put("hibernate.connection.password", hibernateConfig.getPassword());
settings.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
settings.put("hibernate.current_session_context_class", "thread");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(settings).build();
MetadataSources metadataSources = new MetadataSources(serviceRegistry);
Metadata metadata = metadataSources.buildMetadata();
sessionFactory = metadata.getSessionFactoryBuilder().build();
this.entityManager = entityManager;
}
public Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
@Override
public List<StationRoleModel> findAllByRole(RoleModel role) {
EntityGraph<?> graph = entityManager.getEntityGraph("stationrole-entity-graph-with-station");
try (Session session = getCurrentSession()) {
Transaction transaction = session.beginTransaction();
CriteriaBuilder builder = session.getCriteriaBuilder();
//===================================================================
//This line crashes with "Not an entity" which doesn't make sense at all because it IS an entity...
//===================================================================
CriteriaQuery<StationRoleModel> criteria = builder.createQuery(StationRoleModel.class);
Root<StationRoleModel> from = criteria.from(StationRoleModel.class);
criteria.select(from);
criteria.where(builder.equal(from.get("role"), role));
TypedQuery<StationRoleModel> typed = entityManager
.createQuery(criteria)
.setHint("javax.persistence.fetchgraph", graph);
try {
return typed.getResultList();
} catch (final NoResultException nre) {
return new ArrayList<>();
} finally {
transaction.commit();
}
}
}
StationRoleModel.java
@Entity(name = "StationRoleModel")
@Table(name = "station_role")
@Getter
@Setter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@NamedEntityGraph(name = "stationrole-entity-graph-with-station",
attributeNodes = @NamedAttributeNode("station"))
public class StationRoleModel extends BaseEntity {
...
}
Ответ №1:
Мне кажется, что менеджер сущностей или сеанс «не осознают», что эти сущности существуют, например, если бы они находились в отдельном «контексте», если это имеет смысл.
Это потому, что так оно и есть. Вы передаете EntityManager
объект , который связан с существующим EntityManagerFactory
и, следовательно, также SessionFactory
, но в конструкторе вашего репозитория вы создаете новый SessionFactory
. Управление SessionFactory
/ Session
и EntityManagerFactory
/ EntityManager
должно выполняться контейнером (в вашем случае пружиной), поэтому вам не следует возиться с созданием чего-либо из этого. Просто впрысните EntityManager
с @Autowired
и готово.
Комментарии:
1. Ок обязательно пересмотрит этот код и попробует это. Тогда я одобрю ваш ответ (это может занять пару недель!) . Спасибо