Hibernate Criteria API等同于Oracle的Decode

时间:2011-05-02 19:59:44

标签: oracle hibernate

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。

6 个答案:

答案 0 :(得分:1)

结帐org.hibernate.criterion.Projections.sqlProjection(...)

与此answer类似。

答案 1 :(得分:1)

对于您提供的示例,您可以使用COALESCE()。

How to simulate NVL in HQL

答案 2 :(得分:0)

您可以使用sqlRestriction来调用本机解码功能。

  

session.createCriteria(Table.class)。新增(Restrictions.sqlRestriction(“解码({别名} .firstName,空   {别名} .lastName,   {别名} .firstName)“))

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

或者,如果您没有在where或group by中使用该列,则可以返回两个属性并使用Java进行检查。

答案 3 :(得分:0)

结束为其添加公式:

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

我担心这种方法存在跨数据库问题和效率问题,所以我愿意改变已接受的答案。

答案 4 :(得分:0)

您可以使用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
 }   

首先,使用null的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

答案 5 :(得分:0)

如果您可以使用 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;