Java 向HQL查询添加Oracle前导提示

Java 向HQL查询添加Oracle前导提示,java,oracle,hibernate,oracle11g,hql,Java,Oracle,Hibernate,Oracle11g,Hql,我想在我的hql查询中添加前导提示,但是,这个提示将像这个前导(别名),在hibernate中,我不知道sql中的别名是什么,我怎么做 String hql="select s.id from " + StoreHouseInventoryItem.class.getName() + "s ,"+ Storehouse.class.getName() +" ss " 我想向这个查询添加前导提示,但我不知道这两个表的hibernate别名,前导需要别名 hibernate将生成如下sql: s

我想在我的hql查询中添加前导提示,但是,这个提示将像这个前导(别名),在hibernate中,我不知道sql中的别名是什么,我怎么做

 String hql="select s.id from " + StoreHouseInventoryItem.class.getName() + "s ,"+ Storehouse.class.getName() +" ss "
我想向这个查询添加前导提示,但我不知道这两个表的hibernate别名,前导需要别名

hibernate将生成如下sql:

select storeHouse0_.id  from app_item storeHouse0_ 
, app_str storeHouse1_

字符串连接是一个非常严重的问题,可能会导致错误

因此,由于需要改变实体类型,因此需要使用Criteria API,该API允许您使用
org.hibernate.comment
Query提示传递SQL提示,如下所示:

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(StoreHouseInventoryItem.class);
Root address = criteriaQuery.from(Storehouse.class);
criteriaQuery.multiselect(employee, address);
Query query = entityManager
    .createQuery( criteriaQuery)
    .unwrap( org.hibernate.query.Query.class )
    .setComment( "leading(storehouseinventoryitem0_, storehouse1_)" );
List<Object[]> result = query.getResultList();
CriteriaBuilder-CriteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery CriteriaQuery=criteriaBuilder.createQuery();
Root employee=criteriaQuery.from(storeinventoryItem.class);
根地址=criteriaQuery.from(storage.class);
criteriaQuery.multiselect(员工、地址);
Query=entityManager
.createQuery(criteriaQuery)
.unwrap(org.hibernate.query.query.class)
.setComment(“引导(仓库库存项0,仓库1)”;
List result=query.getResultList();
您还必须启用SQL级别的提示:

<property
    name="hibernate.use_sql_comments"
    value="true"
/>

更新
至于知道别名,您只需运行查询,找出Hibernate为每个实体分配了哪些别名,然后应该在Oracle提示中使用这些别名。

我做了以下操作,效果很好:

  • 创建了一个拦截器类

    public class HibernateEntityInterceptor extends EmptyInterceptor {
    
        private static final String HINT_START = "'$HINT-";
        private static final String HINT_END = "-$HINT',";
        private static final String ORACLE_HINT_START = "/*+ ";
        private static final String ORACLE_HINT_END = " */ ";
    
        @Override
        public String onPrepareStatement(String sql) {
    
            if (sql.contains(HINT_START)) {
                String hintText = StringUtils.substringBetween(sql, HINT_START, HINT_END);
                sql = StringUtils.replace(sql, HINT_START + hintText + HINT_END, ORACLE_HINT_START + hintText + ORACLE_HINT_END);
            }
            return sql;
        }
    
        public static String hint(String hint, boolean isEnabled) {
            return isEnabled ? HINT_START + hint + HINT_END : "";
        }
    }
    
  • 在HQL中使用它,如下所示。这里我使用的是“HASH_SJ”oracle提示

    String hql = "select " + HibernateEntityInterceptor.hint("HASH_SJ", true) + " 1 from tableEntityA";
    
  • 注册了拦截器

    jpaProperties.setProperty("hibernate.ejb.interceptor", "com.abc.HibernateEntityInterceptor");
    

  • 你的要求有点不清楚。你能详细说明一下吗?我编辑了这个问题。值得一提的是,当你找出是什么让Oracle optimizer没有做你想做的事情时,这个提示应该是一个临时的工作循环。如果表中的统计信息发生变化,那么如果您得到提示,Oracle将无法使您的查询适应新的“人口统计”。您如何知道别名将是InvetPryItem0,storehous1??