Je suis en veille prolongée 4.3.11.Final sur Java 7 et JPAattribut d'entité Hibernate/JPA avec un UserType pas correctement chargé
J'ai créé un UserType au maréchal/unmarshal un objet ENUM java à la base de données le stocker comme un SMALLINT.
L'énumération est un attribut d'un objet Adresse et représente la zone/localité générale de l'adresse.
Mon problème est le suivant:
Quand je charge l'adresse directement .: par exemple
Address anAddress = session.get(Address.class, 123L);
il charge bien et je peux accéder à la AreaEnum par exemple
assert anAddress.getArea() != null; // ALL GOOD
Cependant, quand j'accéder à une adresse par le biais d'une relation globale d'une autre entité du AreaEnum est pas mobilisée et renvoie un null
, par exemple,
Person aPerson = session.get(Person.class, 5L);
assert aPerson.getAddress().getArea() != null; // FAILS HERE
D'autres attributs standard (qui ont des annotations de définitions de colonnes simples) sont renseignés correctement.
Mon annotation pour l'attribut Zone est comme ceci:
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;
}
...
}
Voici la classe HibernateAreaEnumType UserType:
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));
}
}
La colonne de la zone dans la table d'adresses est définie comme:
+--------------+-----------------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-----------------------+------+-----+-------------------+-----------------------------+ |
| are_id | smallint(5) unsigned | YES | MUL | NULL |
+--------------+-----------------------+------+-----+-------------------+-----------------------------+
Juste pour clarifier les données est tous là dans le tableau.
En parcourant le code, il semble que dans le HibernateAreaEnumType le rs.wasNull()
est de retour true
mais en regardant les données retournées par l'sql select (en utilisant P6Spy) montre que les informations de zone ENUM est là.
Toute aide vraiment apprécié