2009-10-14 6 views
6

J'ai créé un UserType (voir ci-dessous) pour gérer une situation dans notre base de données mySQL où nous avons enregistré des dates nulles comme 0000-00-00 00:00:00. Lorsque j'essaie de conserver mon entité avec une valeur null pour dispDT (voir ci-dessous), elle génère cette exception: "javax.persistence.PersistenceException: org.hibernate.PropertyValueException: la propriété not-null référence une valeur nulle ou transitoire: myEntity .dispDt "Hibernate UserType personnalisé ne fonctionne pas

En définissant un point d'arrêt dans chaque méthode dans MySQLTimeStampUserType, je peux voir qu'il appelle la méthode deepCopy et n'appelle jamais la méthode nullSafeSet. Je pensais que le but de la méthode nuyllSafeSet était de me permettre de manipuler la valeur avant de la persister. Qu'est-ce que je fais mal?

Annotations Entité

@Basic(optional = false) 
@Column(name = "disp_dt") 
@Type(type = "mypackage.MySQLTimeStampUserType") 
// @Temporal(TemporalType.TIMESTAMP) 
private Date dispDt; 

classe Type d'utilisateur

public class MySQLTimeStampUserType implements UserType { 

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

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

public Class returnedClass() { 
    return Date.class; 
} 

public boolean equals(Object x, Object y) throws HibernateException { 
    if (x == y) { 
     return true; 
    } else if (x == null || y == null) { 
     return false; 
    } else { 
     return x.equals(y); 
    } 

} 

public int hashCode(Object arg0) throws HibernateException { 
    throw new UnsupportedOperationException("Not supported yet."); 
} 

public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException { 
    // if the date is 0000-00-00 00:00:00 return null, else return the timestamp 
    Date result = null; 
    if (!resultSet.wasNull()) { 
     if (!resultSet.getString(names[0]).equals("0000-00-00 00:00:00")) { 
      result = resultSet.getDate(names[0]); 
     } 
    } 
    return result; 
} 

public void nullSafeSet(PreparedStatement statement, Object value, int index) throws HibernateException, SQLException { 
    // if the date is null set the value to "0000-00-00 00:00:00" else save the timestamp 
    if (value == null) { 
     statement.setString(index, "0000-00-00 00:00:00"); 
    } else { 
     statement.setTimestamp(index,(Timestamp) value); 
    } 

} 

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

public boolean isMutable() { 
    return false; 
} 

public Serializable disassemble(Object value) throws HibernateException { 
    throw new UnsupportedOperationException("Not supported yet."); 
} 

public Object assemble(Serializable cached, Object owner) throws HibernateException { 
    throw new UnsupportedOperationException("Not supported yet."); 
} 

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

Répondre

4

Votre problème est pas avec votre UserType - c'est le fait que vous avez déclaré votre propriété comme non nulle (en utilisant @Basic en option = "false") et pourtant vous le définissez à null. Cela dit, je ferais attention de ne pas renvoyer la valeur d'origine dans les méthodes deepCopy/assembler/désassembler. java.util.Date est mutable et vous pouvez demander des ennuis là-bas.

+0

La base de données n'autorise pas de valeur nulle pour cette colonne. Au lieu de cela ils l'ont peuplé avec "0000-00-00 00:00:00". Je pensais que le point de UserType était de me permettre de convertir le null en "0000-00-00 00:00:00". – Preston

+2

Je ne parle pas de la base de données. Vous définissez cette propriété à NULL dans votre application; Hibernate rechigne à cela car il est mappé comme optionnel = false. Supprimez cette déclaration et vous serez prêt à partir - la base de données n'aura pas la valeur NULL dans cette colonne parce que votre type d'utilisateur la remplacera par des zéros. – ChssPly76