You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Helidon MP 2.5中Hibernate createQuery()报ORA-00933错误求助

问题

在Helidon MP 2.5环境中连接Oracle数据库,使用Hibernate作为JPA提供者,通过通用抽象CRUD仓库的findAll()方法实现实体分页查询时,抛出ORA-00933错误。

仓库代码

public abstract class CrudRepository<T, ID> implements CrudInterface<T, ID> {

    protected final Class<T> persistentClass;
    private final SessionFactory sessionFactory;
    private static final Logger log = Logger.getLogger(CrudRepository.class.getName());

    protected CrudRepository(Class<T> persistenceClass, HelidonPersistenceUnitInfo hpuInfo) {
        this.persistentClass = persistenceClass;
        this.sessionFactory = new org.hibernate.cfg.Configuration()
                .addProperties(hpuInfo.getProperties())
                .addAnnotatedClass(persistenceClass)
                .buildSessionFactory();
    }

    public Page<T> findAll(Pageable pageableObj) {
        List<T> list;
        int page = pageableObj.getPageNum();
        int size = pageableObj.getMaxRows();

        if(page < 0 || size < 0) {
            throw new IllegalArgumentException("Invalid values for page and size");
        }

        StringBuilder queryStr = new StringBuilder("SELECT e FROM " + persistentClass.getSimpleName() + " e");

        log.info("SQL QUERY IS: " + queryStr.toString());

        try (Session session = sessionFactory.openSession()) {
            Query<T> query = session.createQuery(queryStr.toString(), persistentClass);
            query.setFirstResult(page * size);
            query.setMaxResults(size);
            list = query.getResultList();
            return new Page<T>(list, pageableObj);
        } catch (Exception e) {
            throw new RuntimeException("Failed to find entities", e);
        }

    }
  
}

测试用例

@Test
void getEmployees() throws Exception {
    EmployeeRepository empRepo = new EmployeeRepository();
    Page<Employee> p = empRepo.findAll(new Pageable(0, 20));
    assertEquals(p.getEntities().size(), 20);
}

错误关键信息

Caused by: Error : 933, Position : 22, Sql = SELECT e FROM EMPLOYEE e limit :1 , OriginalSql = SELECT e FROM EMPLOYEE e limit ?, Error Msg = ORA-00933: SQL命令未正确结束

已尝试在查询语句后加分号、改用createSQLQuery()替代createQuery(),问题仍未解决。


原因及解决方案

核心原因

Hibernate生成了MySQL风格的limit分页语法,但Oracle数据库不支持limit关键字(Oracle 12c前用ROWNUM,12c及以后用OFFSET ... FETCH NEXT ... ROWS ONLY)。问题根源是未正确配置Hibernate的Oracle方言,导致Hibernate无法生成适配Oracle的分页SQL。

解决方案

  1. 配置Oracle方言
    在Helidon配置文件(如persistence.xml或application.properties)中添加Hibernate方言配置:

    • Oracle 12c及以上版本:
      hibernate.dialect=org.hibernate.dialect.Oracle12cDialect
      
    • Oracle 11g及以下版本:
      hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
      

    确保该配置被正确加载到hpuInfo.getProperties()中,Hibernate会根据方言自动生成正确的分页SQL。

  2. 手动指定方言(若配置未生效)
    如果Helidon的PersistenceUnitInfo未加载到方言配置,可在SessionFactory创建时手动添加:

    this.sessionFactory = new org.hibernate.cfg.Configuration()
            .addProperties(hpuInfo.getProperties())
            .setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle12cDialect")
            .addAnnotatedClass(persistenceClass)
            .buildSessionFactory();
    
  3. 依赖JPA标准分页API
    无需手动在JPQL中添加分页关键字,setFirstResult()和setMaxResults()是JPA标准分页方法,只要方言配置正确,Hibernate会自动转换为Oracle支持的分页语法。

内容的提问来源于stack exchange,提问作者swing1234

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 08:32:57