2009-04-01 7 views
1

Dans mon schéma, il existe quelques colonnes redondantes utilisées pour accélérer les requêtes de rapport. Par exemple, le total des achats d'une vente est enregistré dans la colonne "purchase_total" du tableau "sale", mais dans le modèle, il est calculé dynamiquement en additionnant le prix de vente de chaque article acheté dans la vente. Cette valeur peut être récupérée en appelant l'accesseur "getPurchaseTotal" sur un objet Vente. Existe-t-il un moyen de mapper cette valeur à la colonne purchase_total dans la table de vente lors de l'insertion/mise à jour, mais ne pas l'inclure dans l'hydratation d'un objet Sale lors du chargement à partir de la base de données? Je suppose que c'est similaire à une colonne dérivée ou calculée mais à l'inverse.Mise en veille prolongée: mappage des colonnes redondantes unidirectionnelles

Est-il préférable de gérer cela via des déclencheurs dans la base de données elle-même?

Répondre

0

Avez-vous essayé d'effectuer les opérations suivantes dans votre modèle?

public class Sales { 

    /** 
    * this set method ignores the value loaded from the database. 
    */ 
    public void setPurchaseTotal(double val) { 
    // ignore a value set explicitly by hibernate 
    } 

    /** 
    * Compute the purchase total 
    */ 
    public double getPurchaseTotal() { 
    // sum item totals 
    double sum = 10.0; 

    return sum; 
    } 

} 

Ceci ignorera les données chargées, mais conservera la valeur lors de leur enregistrement dans la base de données.

HTH

+0

J'ai pensé à cela mais je préférerais ne pas avoir recours à ce que je considère comme un hack. Il est certainement assez courant que de telles colonnes redondantes existent à des fins de reporting. –

0

Hibernate vous permet de créer des types et remplacer le fetching/sauvegarde metods des types.

Créez un type, par exemple InsertableOnly, qui, sur les ensembles de récupération, rejette la valeur de la base de données.

En supposant que votre valeur est un entier parce que vous représentez prix cents pour éviter les problèmes d'arrondi:

class InsertOnlyInteger extends org.hibernate.type.IntegerType { 
    public Object get(ResultSet rs, String name) throws SQLException { 
    return null; 
    } 
} 

Ensuite, faire le type Hibernate de l'attribut InsertOnlyInteger (avec xml ou annotation, comme il vous convient).

C'est une réponse très similaire à la réponse donnée par sewardrobert, mais il

  1. vous permet d'avoir un setter « normal » dans la classe, qui
  2. collaborateurs/autre/que Hibernate (comme votre routine de sommation de code Java) peut alors utiliser normalement,
  3. il est réutilisable, et
  4. avec un nom décent (comme InsertableOnly) c'est plus ou moins auto-documentant.
+0

C'est un peu mieux, mais il faudra encore un setter sur la classe Sale, n'est-ce pas? Je n'ai pas besoin d'un setter (pour des raisons évidentes) donc en ajouter un pour le bien de l'ORM est toujours considéré comme un hack. –

0

Je le ferais probablement dans la base de données, car ces colonnes ne sont pas pertinentes pour votre application principale. Vous pouvez soit utiliser des déclencheurs, soit supprimer complètement les colonnes redondantes et utiliser une vue matérialisée (Oracle PostgreSQL)/vue indexée (SQL Server)/table récapitulative automatique (DB2) pour interroger vos données de rapport.