Hibernate CriteriaBuilder : Не сущность, когда она является сущностью

#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. Ок обязательно пересмотрит этот код и попробует это. Тогда я одобрю ваш ответ (это может занять пару недель!) . Спасибо