使用复合用户类型的hql查询生成的sql

时间:2011-02-21 14:10:40

标签: java hibernate

我正在使用hibernate 3.6.1,我对hql生成的sql有一个奇怪的行为。

这是hql:

from Floor as floor where (floor.type != :var1)

type是一个复合用户类型(参见bottom),如果两个值中的至少一个不同,则由long和int两个值组成,Type与另一个Type不同。 我想提取所有类型与指定类型不同的楼层,因此所有楼层都有floor.oid<> oi1 OR floor.number1<> num1其中oi1和number1来自指定的Type。但是生成的sql有一个AND而不是OR:

select
    floor0_.id as id0_,
    floor0_.number as number0_,
    floor0_.oid as oid0_,
    floor0_.number1 as number4_0_ 
from
    Floor floor0_ 
where
    floor0_.oid<>? 
    and floor0_.number1<>?

我希望条件应该是

floor0_.oid<>? 
or floor0_.number1<>?

现场实施:

public class Floor {
    private Long id;
    private Integer number;
    private Type type;


    public Type getType() {
        return type;
    }

    public void setType(Type type) {
        this.type = type;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }



    public Integer getNumber() {
        return number;
    }

    public void setNumber(Integer number) {
        this.number = number;
    }
}

类型实施:

public class Type implements CompositeUserType {
    private Long oid;
    public Long getOid() {
        return oid;
    }
    public void setOid(Long oid) {
        this.oid = oid;
    }
    private Integer number1;


    public Integer getNumber1() {
        return number1;
    }
    public void setNumber1(Integer number1) {
        this.number1 = number1;
    }


    @Override
    public String[] getPropertyNames() {
        String[] names = {"oid", "number1"};
        return names;
    }
    @Override
    public org.hibernate.type.Type[] getPropertyTypes() {
        BasicTypeRegistry registry = new BasicTypeRegistry();
        org.hibernate.type.Type longType = registry.getRegisteredType(LongType.INSTANCE.getRegistrationKeys()[0]);
        org.hibernate.type.Type intType = registry.getRegisteredType(IntegerType.INSTANCE.getRegistrationKeys()[0]);
        org.hibernate.type.Type[] types = { longType, intType };
        return types;
    }
    @Override
    public Object getPropertyValue(Object component, int property)
            throws HibernateException {
        if (component == null) return null;
        if (! (component instanceof Type)) {
            throw new HibernateException("wrong component type");
        }
        Type type = (Type) component;
        switch(property) {
        case 0:
            return type.oid;
        case 1: 
            return type.number1;
        default:
            throw new HibernateException("wrong component type");
        }
    }
    @Override
    public void setPropertyValue(Object component, int property, Object value)
            throws HibernateException {
        // boh!!!
        if (component == null) {
            throw new HibernateException("set property invoked on a null instance");
        }
        if (! (component instanceof Type)) {
            throw new HibernateException("set property invoked on a wrong component type");
        }
        Type type = (Type) component;
        String valueString = value.toString();
        switch(property) {
        case 0:
            type.oid  = Long.parseLong(valueString);
        case 1: 
            type.number1 = Integer.parseInt(valueString);
        default:
            throw new HibernateException("set property invoked on a wrong component type");
        }

    }
    @Override
    public Class returnedClass() {
        // TODO Auto-generated method stub
        return Type.class;
    }
    @Override
    public boolean equals(Object x, Object y) throws HibernateException {
        if(x == y) return true;
        if (x == null && y != null) return false;
        if (x != null && y == null) return false;
        if(! (x instanceof Type) || ! (y instanceof Type)) {
            return false;   
        }
        Type xt = (Type)x;
        Type yt = (Type)y;
        return (xt.oid == yt.oid && xt.number1 == yt.number1);
    }

    @Override
    public int hashCode(Object x) throws HibernateException {
        if (x == null) {
            return 0;
        } else {
            if (x instanceof Type) {
                Type xt = (Type) x;
                return xt.number1.hashCode() * 17 + xt.oid.hashCode();
            } else {
                throw new HibernateException("hashCode invoked on a non Type instance");
            }
        }
    }
    @Override
    public Object nullSafeGet(ResultSet rs, String[] names,
            SessionImplementor session, Object owner)
            throws HibernateException, SQLException {

        Type t = null;
        if (!rs.wasNull()){
            t = new Type();

            Long id = rs.getLong(names[0]);
            Integer number = rs.getInt(names[1]);

            t.oid = id;
            t.number1 = number;
        }
        return t;
    }
    @Override
    public void nullSafeSet(PreparedStatement st, Object value, int index,
            SessionImplementor session) throws HibernateException, SQLException {
        Type t = (Type) value;

        st.setLong(0, t.oid);
        st.setInt(1, t.number1);

    }

    @Override
    public Object deepCopy(Object value) throws HibernateException {
        if (value == null)
            return null;

        Type oldType = (Type) value;

        Type t = new Type();
        t.setOid(oldType.getOid());
        t.setNumber1(oldType.getNumber1());

        return t;
    }

    @Override
    public boolean isMutable() {
        return false;
    }

    @Override
    public Serializable disassemble(Object value, SessionImplementor session)
            throws HibernateException {
        return value.toString();
    }

    @Override
    public Object assemble(Serializable cached, SessionImplementor session,
            Object owner) throws HibernateException {
        return cached;
    }
    @Override
    public Object replace(Object original, Object target,
            SessionImplementor session, Object owner) throws HibernateException {

        return original;
    }

}

有什么我错的吗?

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

这肯定是Hibernate中的一个错误,请report it随意。

作为一种解决方法,您可以使用Critera进行此查询,但它没有此错误。

另请注意,CompositeUserType通常用于保留其他类,而不是同一个类,因此Type的实现可能会造成混淆,请参阅6.4.3. Custom types using org.hibernate.usertype.CompositeUserType