简体   繁体   English

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

[英]sql generated with hql query with composite user type

I'm using hibernate 3.6.1 and i have a strange behaviour on the sql generated by hql. 我正在使用休眠3.6.1,并且在hql生成的sql上我有一个奇怪的行为。

Here is the hql: 这是hql:

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

type is a composite user type (see bottom) and is composed by two values a long and an int and a Type is different from another Type if at least one of the two values is different. type是一个复合用户类型(请参阅底部),由两个值long和一个int组成,并且如果两个值中的至少一个不同,则Type与另一个Type不同。 I want to extract all the floors with type different from a specified one, so all the floor with floor.oid<>oi1 OR floor.number1<>num1 where oi1 and number1 is from a specified Type. 我要提取类型与指定楼层不同的所有楼层,因此所有楼层都为floor.oid <> oi1或floor.number1 <> num1,其中oi1和number1来自指定的Type。 But the generated sql has an AND instead a OR: 但是生成的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<>?

i expect that the condition should be 我希望条件应该是

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

Floor implementation: 发言权实施:

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;
    }
}

Type implementation: 类型实现:

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;
    }

}

is there something i'm wrong ? 我有什么问题吗?

Thanks for any help 谢谢你的帮助

It's certainly a bug in Hibernate, feel free to report it . 在Hibernate中肯定是一个错误,请随时进行报告

As a workaround you can use Critera for this query, it doesn't have this bug. 作为解决方法,您可以使用Critera进行此查询,因为它没有此错误。

Also note that CompositeUserType is usually used to persist another class, not the same one, therefore your implementation of Type can be confusing, see 6.4.3. 还要注意, CompositeUserType通常用于持久化另一个类,而不是同一个类,因此您对Type的实现可能会令人困惑,请参见6.4.3。 Custom types using org.hibernate.usertype.CompositeUserType . 使用org.hibernate.usertype.CompositeUserType的自定义类型

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM