SQL генерируется с помощью hql-запроса с составным типом пользователя - PullRequest
1 голос
/ 21 февраля 2011

Я использую hibernate 3.6.1, и у меня странное поведение на sql, сгенерированном hql.

Вот hql:

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

тип является составным типом пользователя (см. Внизу) и состоит из двух значений long и типа int и Type отличается от другого типа, если хотя бы одно из двух значений отличается. Я хочу извлечь все этажи с типом, отличным от указанного, поэтому весь этаж с floor.oid <> oi1 ИЛИ floor.number1 <> num1, где oi1 и number1 - из указанного типа. Но сгенерированный 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 голосов
/ 21 февраля 2011

Это определенно ошибка в Hibernate, не стесняйтесь сообщить об этом .

В качестве обходного пути вы можете использовать Critera для этого запроса, у него нет этой ошибки.

Также обратите внимание, что CompositeUserType обычно используется для сохранения другого класса, а не того же самого, поэтому ваша реализация Type может сбивать с толку, см. 6.4.3. Пользовательские типы, использующие org.hibernate.usertype.CompositeUserType .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...