【问题标题】:Oracle char type issue in Hibernate HQL queryHibernate HQL 查询中的 Oracle 字符类型问题
【发布时间】:2014-05-16 16:06:32
【问题描述】:

我有 Oracle 表,其中包含 char 类型的列。在我的 Entity 类中,我将 oracle char 类型映射到 java string 类型。

这是我的实体类的代码。

@Entity
@Table(name="ORG")
public class Organization  {

private String serviceName;
private String orgAcct;

     //Some other properties goes here...

@Column(name="ORG_ACCT", nullable=false, length=16)
public String getOrgAcct() {
    return this.orgAcct;
}

public void setOrgAcct(String orgAcct) {
    this.orgAcct = orgAcct;
}


@Column(name="SERVICE_NAME",nullable=true, length=16)
public String getServiceName() {
    return this.serviceName;
}

public void setServiceName(String serviceName) {
    this.serviceName = serviceName;
}

}

这里的 serviceName 和 orgAcct 都是 Oracle 中的 char 类型变量

在我的 DAO 类中,我编写了一个 HQL 查询来使用 serviceName 和 orgAcct 属性获取 Oranization 实体对象。

@Repository
@Scope("singleton") //By default scope is singleton
public class OrganizationDAOImpl implementsOrganizationDAO {

public OrganizationDAOImpl(){
}

public Organization findOrganizationByOrgAcctAndServiceName(String orgAcct,String serviceName){
    String hqlQuery = "SELECT org FROM  Organization org WHERE org.serviceName = :serName AND org.orgAcct = :orgAct";
    Query query = getCurrentSession().createQuery(hqlQuery)
        .setString("serName", serviceName)
        .setString("orgAct", orgAcct);

    Organization org =  findObject(query);
    return org;
}
 }

但是当我调用 findOrganizationByOrgAcctAndServiceName() 方法时,我将组织对象设为 null(即 HQL 查询未检索 Char 类型数据)。

请帮我解决这个问题。这里我无法将 Oracle 类型 char 更改为 Varchar2。我需要使用 oracle char 类型变量。

@EngineerDollery 在抛出上面的帖子后,我用 columnDefinition 修改了我的 Entity 类,@Column 注释属性。

@Column(name="SERVICE_NAME",nullable=true,length=16,columnDefinition="CHAR")
    public String getServiceName() {
        return this.serviceName;
    }

但我仍然无法检索相应列的数据。

我还在 columnDefinition 属性中添加了列大小。

@Column(name="SERVICE_NAME",nullable=true,length=16,columnDefinition="CHAR(16)

但我仍然面临同样的问题。 有什么我做错了吗。请帮帮我。

【问题讨论】:

  • 当您从 SQL 客户端对数据库手动运行 SQL 时,您是否看到任何返回的行?
  • @EngineerDollery 在抛出上述帖子后,我使用 columnDefinition 和 column annoation 属性修改了我的 Entity 类。 @Column(name="SERVICE_NAME",nullable=true,length=16,columnDefinition="CHAR") public String getServiceName() { return this.serviceName; } 但我仍然无法检索相应列的数据。我也在 columnDefinition 属性中添加了列大小。 @Column(name="SERVICE_NAME",nullable=true,length=16,columnDefinition="CHAR(16) 但我仍然面临同样的问题。有什么我做错了吗。请帮帮我。
  • 使用char 几乎总是错误的选择。鉴于您遇到的问题,我很确定您确实想使用varchar。存储数据时,char 始终填充到定义的长度。我很确定这不是你想要的。
  • @a_horse_with_no_name 我无法将 serviceName 的类型从 char 更改为 varchar2。因为其他 API(用 C++ 编码)正在使用相同的数据库。我们可以为这个问题提供通用解决方案吗?

标签: oracle hibernate types char hql


【解决方案1】:

我使用 OraclePreparedStatement 和 Hibernate UserType 接口解决了这个问题。

通过扩展 org.hibernate.usertype.UserType 接口创建了一个新的 UserType 类,并提供了 nullSafeSet()、nullSafeGet() 方法的实现。

nullSafeSet() 方法,我们有第一个参数为 PreparedStatement,在该方法中我将 PreparedStatement 转换为 OraclePreparedStatement 对象并使用 setFixedCHAR() 方法传递字符串值。

这里是UserType impl类的完整代码。

package nc3.jws.persistence.userType;

import java.io.Serializable;
import java.sql.PreparedStatement; 
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import org.apache.commons.lang.StringUtils;
import org.hibernate.type.StringType;
import org.hibernate.usertype.UserType;

/**
* 
* based on www.hibernate.org/388.html
*/

 public class OracleFixedLengthCharType implements UserType {

public OracleFixedLengthCharType() {
    System.out.println("OracleFixedLengthCharType constructor");
}

public int[] sqlTypes() {
    return new int[] { Types.CHAR };
}



public Class<String> returnedClass() {
    return String.class;
}

public boolean equals(Object x, Object y) {
    return (x == y) || (x != null && y != null && (x.equals(y)));
}

@SuppressWarnings("deprecation")
public Object nullSafeGet(ResultSet inResultSet, String[] names, Object o) throws SQLException {
    //String val = (String) Hibernate.STRING.nullSafeGet(inResultSet, names[0]);
    String val = StringType.INSTANCE.nullSafeGet(inResultSet, names[0]);
    //System.out.println("From nullSafeGet method valu is "+val);
    return val == null ? null : StringUtils.trim(val);
}


public void nullSafeSet(PreparedStatement inPreparedStatement, Object o,
        int i)
                throws SQLException {

    String val = (String) o;
    //Get the delegatingStmt object from DBCP connection pool PreparedStatement object.
    org.apache.commons.dbcp.DelegatingStatement delgatingStmt = (org.apache.commons.dbcp.DelegatingStatement)inPreparedStatement;
    //Get OraclePreparedStatement object using deletatingStatement object.

    oracle.jdbc.driver.OraclePreparedStatement oraclePreparedStmpt = (oracle.jdbc.driver.OraclePreparedStatement)delgatingStmt.getInnermostDelegate();
    //Call setFixedCHAR method, by passing string type value .
    oraclePreparedStmpt.setFixedCHAR(i, val);
}


public Object deepCopy(Object o) {
    if (o == null) {
        return null;
    }
    return new String(((String) o));
}


public boolean isMutable() {
    return false;
}

public Object assemble(Serializable cached, Object owner) {
    return cached;
}


public Serializable disassemble(Object value) {
    return (Serializable) value;
}

public Object replace(Object original, Object target, Object owner) {
    return original;
}

public int hashCode(Object obj) {
    return obj.hashCode();
}

  }

在 Entity 类中使​​用 @TypeDefs 注解配置此类。

@TypeDefs({
@TypeDef(name = "fixedLengthChar", typeClass = nc3.jws.persistence.userType.OracleFixedLengthCharType.class)

})

将此类型添加到 CHAR 类型列

@Type(type="fixedLengthChar")
@Column(name="SERVICE_NAME",nullable=true,length=16)
public String getServiceName() {
    return this.serviceName;
}

【讨论】:

    【解决方案2】:

    char 类型在表格中用空格填充。这意味着如果你有

    foo
    

    在其中一列中,您实际拥有的是

    foo<space><space><space>...
    

    直到字符串的实际长度为 16。

    因此,如果您正在寻找一个以 "foo" 作为其服务名称的组织,您将找不到任何名称,因为表中的实际值 if foo 用 13 个空格填充。

    因此,您必须确保所有查询参数也用空格填充。

    【讨论】:

    • 我无法在运行时预测 serviceName 的值,如何在 serviceName 中附加空格
    • 您使用循环来追加空格,直到字符串的长度为 16。
    猜你喜欢
    • 2015-02-15
    • 1970-01-01
    • 1970-01-01
    • 2014-07-11
    • 1970-01-01
    • 2011-02-10
    • 1970-01-01
    • 2016-04-21
    • 1970-01-01
    相关资源
    最近更新 更多