【问题标题】:Hibernate Criteria API Equivalent to Oracle's DecodeHibernate Criteria API 等价于 Oracle 的解码
【发布时间】:2011-08-17 05:45:24
【问题描述】:

在 Hibernate Criteria API 中相当于 Oracle 的 DECODE() 函数是什么?

我需要做的一个 SQL 示例:

SELECT DECODE(FIRST_NAME, NULL, LAST_NAME, FIRST_NAME) as NAME ORDER BY NAME;

如果 FIRST_NAME 为 NULL,则返回 LAST_NAME 给 NAME。

我更喜欢使用 Criteria API,但如果没有其他方法,我可以使用 HQL。

【问题讨论】:

  • 仅供参考,您的解码相当于NVL(FIRST_NAME, LAST_NAME)COALESCE(FIRST_NAME, LAST_NAME)

标签: oracle hibernate


【解决方案1】:

查看org.hibernate.criterion.Projections.sqlProjection(...)

类似于这个answer

【讨论】:

  • 看起来我可以将它与@Jeffrey 的建议结合使用 COALESCE() 但 hib 抱怨“名称”不存在。想法? criteria.setProjection(Projections.sqlProjection("coalesce(first_name, last_name)", new String[] {"name"}, new Type[] {Hibernate.STRING}));
【解决方案2】:

对于您给出的示例,您可以使用 COALESCE()。

How to simulate NVL in HQL

【讨论】:

    【解决方案3】:

    可以使用sqlRestriction调用原生解码函数。

    session.createCriteria(Table.class).add(Restrictions.sqlRestriction("decode({alias}.firstName,null, {别名}.lastName, {别名}.firstName)"))

    使用 HQL,Oracle 方言已经具有 coalesce 和 nvl 函数,或者如果您确实需要解码,您可以子类化方言并将其添加为自定义函数。我不知道 Hibernate 是否像 decode 那样支持可变长度的参数数量,但最坏的情况是,您可以创建 decode1、decode2 等来支持不同数量的参数。

    或者,如果您不使用 where 或 group by 中的列,您可以将这两个属性都带回并在 Java 中进行检查。

    【讨论】:

      【解决方案4】:

      最后为它添加了一个公式:

      <property name="name" formula="coalesce(first_name, last_name)"/>
      

      我担心这种方法的跨数据库问题和可能的效率问题,因此我愿意更改已接受的答案。

      【讨论】:

        【解决方案5】:

        您可以使用 Hibernate @Type 属性,根据您的要求,您可以自定义注释并应用在字段之上。喜欢:

        public class PhoneNumberType implements UserType {
        @Override
        public int[] sqlTypes() {
           return new int[]{Types.INTEGER, Types.INTEGER, Types.INTEGER};
        }
        
         @Override
        public Class returnedClass() {
        return PhoneNumber.class;
        }
        
         // other methods
         }   
        

        一、空SafeGet方法:

         @Override
         public Object nullSafeGet(ResultSet rs, String[] names, 
         SharedSessionContractImplementor session, Object owner) throws HibernateException,                
         SQLException {
         int countryCode = rs.getInt(names[0]);
         if (rs.wasNull())
          return null;
          int cityCode = rs.getInt(names[1]);
         int number = rs.getInt(names[2]);
         PhoneNumber employeeNumber = new PhoneNumber(countryCode, cityCode, number);
          return employeeNumber;
          }
        

        接下来,null SafeSet 方法:

         @Override
          public void nullSafeSet(PreparedStatement st, Object value, 
          int index, SharedSessionContractImplementor session) 
            throws HibernateException, SQLException {
             if (Objects.isNull(value)) {
             st.setNull(index, Types.INTEGER);
             } else {
             PhoneNumber employeeNumber = (PhoneNumber) value;
             st.setInt(index,employeeNumber.getCountryCode());
             st.setInt(index+1,employeeNumber.getCityCode());
             st.setInt(index+2,employeeNumber.getNumber());
           }
          }
        

        最后,我们可以在我们的 OfficeEmployee 实体类中声明我们自定义的 PhoneNumberType:

         @Entity
         @Table(name = "OfficeEmployee")
          public class OfficeEmployee {
        
           @Columns(columns = { @Column(name = "country_code"), 
           @Column(name = "city_code"), @Column(name = "number") })
           @Type(type = "com.baeldung.hibernate.customtypes.PhoneNumberType")
            private PhoneNumber employeeNumber;
        
         // other fields and methods
           }
        

        这可能会解决您的问题,这将适用于所有数据库。如果您想了解更多信息,请参考 :: https://www.baeldung.com/hibernate-custom-types

        【讨论】:

          【解决方案6】:

          如果您可以使用 HQL,您可以将 DECODE 替换为 CASE。

          您可以更新您的查询,

          SELECT DECODE(FIRST_NAME, NULL, LAST_NAME, FIRST_NAME) as NAME ORDER BY NAME;
          

          到,

          SELECT CASE WHEN FIRST_NAME = NULL then LAST_NAME ELSE FIRST_NAME END as NAME ORDER BY NAME;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-02-17
            • 1970-01-01
            • 2011-11-01
            • 2015-07-24
            • 2013-11-12
            • 2013-06-21
            • 1970-01-01
            相关资源
            最近更新 更多