2010-06-07 14 views
0

Utilisation de Play! framework et sa classe JPASupport J'ai rencontré un problème avec une base de données existante.Mapper la colonne null en tant que 0 dans une base de données héritée (JPA)

J'ai la classe suivante:

@Entity 
@Table(name="product_catalog") 
public class ProductCatalog extends JPASupport { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    public Integer product_catalog; 

    @OneToOne 
    @JoinColumn(name="upper_catalog") 
    public ProductCatalog upper_catalog; 

    public String name; 
} 

Certains catalogues de produits n'ont pas un catalogue supérieur, ce qui est référencé comme 0 dans une base de données existante. Si je fournis le fichier upper_catalog comme NULL, alors JPA insère une valeur NULL dans cette colonne de base de données. Comment puis-je forcer les valeurs NULL à être 0 lors de l'écriture dans la base de données et l'inverse lors de la lecture de la base de données?

Répondre

2

Je ne vois pas de moyen facile d'atteindre ce que vous voulez avec JPA directement (et il y a de grandes chances que même si vous trouvez un moyen qui fonctionne avec une opération de base comme sauvegarder ou charger, ça ne marchera pas avec plus cas d'utilisation complexe, comme critères complexes/hql, aucun mode fetching standard, etc.)

donc, je le ferais:

@Entity 
@Table(name="product_catalog") 
public class ProductCatalog extends JPASupport { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    public Integer product_catalog; 

    @Column(name="upper_catalog") 
    public Long upper_catalog_id; 

    public String name; 

    public ProductCatalog getUpperCatalog() { 
     if (upper_catalog_id == 0) 
     return null; 

     return ProductCatalog.findById(upper_catalog_id); 
    } 

    public void setUpperCatalog(ProductCatalog pc) { 
     if (pc == null) { 
     upper_catalog_id = 0; 
     } 
     else { 
     if (pc.id == null) { 
      // option 1. a bit like a cascade 
      pc.save(); 
      // option 2. if you consider passing a transient entity is not valid 
      throw new RuntimeException("transient entity " + pc.toString()); 
     } 
     upper_catalog_id = pc.id; 
     } 
    } 
} 
+0

Merci, cela fonctionne parfaitement! Juste dû changer le long à l'entier (une certaine configuration de jeu!). Quelle est la signification de @Transient dans ce cas - je n'ai pas ajouté cela et tous mes tests pour cette classe semblent bien se passer. – Indrek

+0

@Transient est compris par le fournisseur JPA comme: "ne gère pas ce champ (ne le sauvegarde pas dans la base de données))". J'ai oublié ça avec le jeu! @Transient est seulement nécessaire sur les champs. J'ai utilisé Long parce que c'est le jeu par défaut! tapez pour id, mais utilisez ce que vous voulez – Thierry

+0

Je viens de relire le code, et vous devriez faire attention à appeler le setter seulement avec ProductCatalog persistant (avec un id) sinon cela ne fonctionnera pas. (Perhap vous devez ajouter ce test au début de la méthode: si pc.id est nul, persister pc). – Thierry

0

Je vois deux options:

  • Utilisez un type de données primitive comme Id (c.-à-d. int au lieu de Integer)
  • Si vous utilisez Hibernate en tant que fournisseur JPA, utilisez un CustomType pour effectuer la conversion