2016-11-15 43 views
0

我上的Java 7和JPA与一个UserType休眠/ JPA实体属性不正确加载

运行的Hibernate。4.3.11.Final我创建了一个用户类型编组/解组一个Java枚举对象数据库将其存储为SMALLINT。

枚举是地址对象的一个​​属性,表示地址的一般区域/地点。

我的问题是这样的:

当我加载地址直接例如为:

Address anAddress = session.get(Address.class, 123L); 

它加载很好,我可以访问AreaEnum例如

assert anAddress.getArea() != null; // ALL GOOD 

然而,当我通过从另一实体的集合关系访问的地址的AreaEnum没有编组并返回一个null,例如

Person aPerson = session.get(Person.class, 5L); 

assert aPerson.getAddress().getArea() != null; // FAILS HERE 

其他标准属性(具有简单的列定义注释)被填充好。

我的区域属性的注释是这样的:

public class Address { 
... 
    @Type(type = "mls.dao.util.HibernateAreaEnumType") 
    @Column(name = "are_id", nullable = false, updatable = true, columnDefinition = "SMALLINT") 
    public AreaEnum getArea() { 
     return this.area; 
    } 

    @Override 
    public void setArea(AreaEnum _area) { 
     this.area = _area; 
    } 
... 
} 

这里是HibernateAreaEnumType用户类型类:

public class HibernateAreaEnumType implements UserType { 

    private final Method parseMethod; 

    private final Class clazz; 

    public HibernateAreaEnumType() { 

     clazz = AreaEnum.class; 
     try { 
     // this is a static method 
     this.parseMethod = clazz.getMethod("parseEnum", Long.class); 
     } catch (Exception e) { 
     throw new IllegalStateException("issue with trying get the parse method of this enum class: " + clazz.getSimpleName(), e); 
     } 
    } 

    @Override 
    public Object nullSafeGet(ResultSet _rs, String[] _names, SessionImplementor _sessionImplementor, Object _owner) throws HibernateException, SQLException { 

     Object result = null; 

     if (!_rs.wasNull()) { 
     Long enumId = (long) _rs.getInt(_names[0]); 
     try { 
      result = this.parseMethod.invoke(null, enumId); 
     } catch (Exception e) { 
      throw new HibernateException("issue trying to method to parse value to make enum: " + enumId, e); 
     } 
     } 

     return result; 
    } 

    @Override 
    public void nullSafeSet(PreparedStatement _ps, Object _value, int _index, SessionImplementor _sessionImplementor) throws HibernateException, SQLException { 
     try { 
     if (null == _value) { 
      _ps.setNull(_index, Types.SMALLINT); 
     } else { 
      _ps.setLong(_index, ((MarshallableIdEnum) _value).getId()); 
     } 
     } catch (ClassCastException e) { 
     throw new IllegalStateException(this.getClass().getName() + ", issue: " + _value + "/" + _index, e); 
     } 
    } 


    private static final int[] SQL_TYPES = {Types.SMALLINT}; 

    public int[] sqlTypes() { 
     return SQL_TYPES; 
    } 


    public Class returnedClass() { 
     return this.clazz; 
    } 

    @Override 
    public Object deepCopy(Object value) throws HibernateException { 
     return value; 
    } 

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

    @Override 
    public Object assemble(Serializable cached, Object owner) throws HibernateException { 
     return cached; 
    } 

    @Override 
    public Serializable disassemble(Object value) throws HibernateException { 
     return (Serializable) value; 
    } 

    @Override 
    public Object replace(Object original, Object target, Object owner) throws HibernateException { 
     return original; 
    } 

    @Override 
    public int hashCode(Object x) throws HibernateException { 
     return x.hashCode(); 
    } 

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

} 

在地址表中的区域栏定义为:

+--------------+-----------------------+------+-----+-------------------+-----------------------------+ 
| Field  | Type     | Null | Key | Default   | Extra      | 
+--------------+-----------------------+------+-----+-------------------+-----------------------------+       | 
| are_id  | smallint(5) unsigned | YES | MUL | NULL          | 
+--------------+-----------------------+------+-----+-------------------+-----------------------------+ 

只是为了澄清表中的数据。

通过单步执行代码,似乎在HibernateAreaEnumType中rs.wasNull()返回true,但查看从sql select返回的实际数据(使用p6spy),表明区域枚举信息存在。

任何帮助非常感激

回答

0

的问题是,我根本不明白ResultSet.wasNull()调用表示什么。

即它报告最后一列读取是否具有SQL NULL值。 。

https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html

而且是否有一个空的结果集(这是我以前所认为

通过undestanding这个我从改变nullSafeGet方法:

@Override 
    public Object nullSafeGet(ResultSet _rs, String[] _names, SessionImplementor _sessionImplementor, Object _owner) throws HibernateException, SQLException { 

     Object result = null; 

     if (!_rs.wasNull()) { 
     Long enumId = (long) _rs.getInt(_names[0]); 
     try { 
      result = this.parseMethod.invoke(null, enumId); 
     } catch (Exception e) { 
      throw new HibernateException("issue trying to method to parse value to make enum: " + enumId, e); 
     } 
     } 

     return result; 
    } 

@Override 
    public Object nullSafeGet(ResultSet _rs, String[] _names, SessionImplementor _sessionImplementor, Object _owner) throws HibernateException, SQLException { 

     Object result = null; 
     Short shortId = StandardBasicTypes.SHORT.nullSafeGet(_rs, _names[0], _sessionImplementor); 

     if (shortId != null) { 
     log.debug("setting: " + _names[0] + " : " + _rs.wasNull() + " : " + _owner); 
     Long enumId = shortId.longValue(); 
     try { 
      result = this.parseMethod.invoke(null, enumId); 
     } catch (Exception e) { 
      throw new HibernateException("issue trying to method to parse value to make enum: " + enumId, e); 
     } 
     } else { 
     result = null; 
     } 

     return result; 
    } 

然后它工作。