I'm using hibernate 3.6.1 and i have a strange behaviour on the sql generated by hql.
Here is the 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. 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. But the generated sql has an AND instead a 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 Hibernat开发者_JAVA百科eException {
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.
As a workaround you can use Critera for this query, it doesn't have this bug.
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. Custom types using org.hibernate.usertype.CompositeUserType.
精彩评论