2009-07-01 6 views
0

Nous avons des tables avec des colonnes héritées dans lesquelles les chaînes SpecialStrings sont stockées. Ces SpecialStrings ne peuvent pas être NULL et elles sont égales à SPECIAL_UNICODE_NULL. Donc, pour renvoyer une entité à un client via JAX-WS, nous devons soit implémenter le wrapper Entity entier pour l'envoyer au lieu de Entity, soit ajouter explicitement la logique de conversion aux méthodes Entity get. Nous voulons utiliser notre propre annotation @LegacyString.Modifier la façon dont les valeurs Entity Bean sont visualisées à l'aide de vos propres annotations

@Column(name="A_LEGACY_COLUMN") 
@LegacyString 
public String oneOfThenLegacyColumn; 

Et puis dans l'auditeur de l'entité par défaut @PostLoad nous transformer tous les champs de @LegacyString à chaîne régulière en utilisant la transformation appropriée.

Mais le problème avec une telle solution est que, après les modifications post-chargement, l'entité est considérée comme modifiée et Entity Manager essayera de la mettre à jour dans la base de données. Bien sûr, je peux utiliser la méthode @PreUpdate pour annuler les modifications. Mais je ne suis pas sûr que cela empêchera Entity de véritable mise à jour.

Donc la question est: Comment changer les valeurs Entity Bean View via propres annotations?

P.S. Je creuse un peu sur ClassLoader et je vais considérer la variante avec l'ajout de changements dans le temps de chargement. Mais je ne peux pas trouver un exemple raisonnable avec le cas de chargeur de classe Application Server.

Répondre

2

Vous pouvez gérer des cas spéciaux comme celui-ci dans Hibernate en créant votre propre implémentation de org.hibernate.usertype.UserType.

public class SpecialStringUserType implements UserType { 

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

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

    public Class returnedClass() { 
    return String.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 Object nullSafeGet(ResultSet resultSet, 
     String[] names, Object owner) 
     throws HibernateException, SQLException { 
    String result = resultSet.getString(names[0]); 
    if ("SPECIAL_UNICODE_NULL".equals(result)) { 
     return null; 
    } 
    return result; 
    } 

    public void nullSafeSet(PreparedStatement statement, 
     Object value, int index) 
     throws HibernateException, SQLException { 
    if (value == null) { 
     statement.setString(index, "SPECIAL_UNICODE_NULL"); 
    } else { 
     statement.setString(index, value); 
    } 
    } 

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

    public boolean isMutable() { 
    return false; 
    } 
} 

Au lieu d'utiliser votre propre @LegacyString annotation procédez comme suit:

@Column(name="A_LEGACY_COLUMN") 
@Type(type = "SpecialStringUserType") 
public String oneOfThenLegacyColumn; 
+0

Je vais vérifier aujourd'hui. Ça a l'air joli. Qu'en est-il de la même chose mais avec TopLink? Peut-il être en quelque sorte un vendeur croisé? –

+0

Malheureusement, cette fonctionnalité n'est pas disponible dans la spécification JPA actuelle, mais la plupart des fournisseurs JPA disposent d'extensions pour l'ajouter. Pour TopLink, vous devez implémenter oracle.toplink.mappings.converters.Converter je crois. Il semble plus compliqué de l'ajouter à votre Entité, jetez un oeil à http://markmail.org/message/lc47ejjlmsflkxdn – mtpettyp

Questions connexes