2016-08-11 1 views
0

deux entités Prix < -1 ---- 1->PriceDetail mappée OneToOne.JPA: relation de mise à jour pour une nouvelle i-mère ont entité

comment puis-je gérer différents scénarios pour cette relation. donc j'ai des cas où je veux toujours un nouveau prix et un nouveau prix, mais je serais également en mesure de créer un nouveau prix seulement et mettre à jour le pricedetail (avec des données d'une entité de prix précédente). ma solution actuelle est de supprimer l'entité de prix pricedail, comment peut-il être fait avec la mise à jour de l'entité pricedetail-priced?

@Entity 
class Price { 

    @OneToOne(cascade=CascadeType.ALL,mappedBy = "price") 
    private PriceDetail priceDetail; 
} 

@Entity 
class PriceDetail { 

    @OneToOne 
    private Price price; 
} 

sauver méthode:

EntityManage em = getEntityManager(); 

for (Price price : getAllPrices()){ 

    Price oldPrice = Price.getById(price.getId());    

    if (!oldPrice.equals(price)){ //if we have price-changes 

    if (PriceCatalog.entryExists(oldPrice)){ //if the current-price is in a catalog 

     //current solution: remove entry from PriceDetail, but i want to update PriceDetail-Entity, pointing 
     //to the newly created price 
     em.remove(oldPrice.getPriceDetail()); 
     em.commitTransaction(); 

     oldPrice.setActive(false); //referenced price in PriceCatalog is now inactive     

     //sets id null, so that a new price-entity is created 
     price.setId(null);    
     price.setActive(true);       
     em.persist(price); //also inserts a new price-detail 

    }else { 
     em.merge(price); 
    } 
    }       
} 
em.commitTransaction(); 

en raison de CascadeType.ALL-Annotation dans le prix-entité, JPA tente d'insérer une nouvelle PriceDetail-entité.

approche 1:

price.getPriceDetail().setId(oldPrice.getPriceDetail().getId()); 

-> Erreur: insérer dans pricedetail viole-contrainte unique: la clé existe déjà

approche 2:

//ommit cascade 
    @OneToOne(mappedBy = "price") 
    protected PriceDetail priceDetail; 

approche alors 1 œuvres, mais la création un nouveau prix complet entraîne: Pendant la synchronisation, un nouvel objet a été trouvé via une relation qui n'a pas été marquée en cascade. PERSIST

Répondre

1

approche 2 n'est pas une option en vous cas, cela est la mise en correspondance correcte de faire un à une association bidirectionnelle:

//you must do this to handle the bidirectional association 
    @OneToOne(mappedBy = "price") 
    protected PriceDetail priceDetail; 

Maintenant, le problème est: le prix est une nouvelle entité alors la entityManager appellera l'opération persit sur price.getpriceDetail() car la cascade persist est déclenchée automatiquement (pas cascade-merge) pour éviter ce comportement étrange, vous pouvez faire ce qui suit.

EntityManage em = getEntityManager(); 

for (Price price : getAllPrices()){ 

    Price oldPrice = Price.getById(price.getId());    

    if (!oldPrice.equals(price)){ //if we have price-changes 

    if (PriceCatalog.entryExists(oldPrice)){ //if the current-price is in a catalog 

     //current solution: remove entry from PriceDetail, but i want to update PriceDetail-Entity, pointing 
     //to the newly created price 
     //em.remove(oldPrice.getPriceDetail()); 
     //em.commitTransaction(); 

     oldPrice.setActive(false); //referenced price in PriceCatalog is now inactive     

     PriceDetail priceDetailold = price.getPriceDetail(); 
     price.setPriceDetail(null); 
     priceDetailold.setPrice(null); 
     //sets id null, so that a new price-entity is created 
     price.setId(null);    
     price.setActive(true); 

     em.persist(price); //inserts a new price 
     price.setPriceDetail(priceDetailold); 
     em.merge(price);// attach the pricedetail to the price 
    }else { 
     em.merge(price); 
    } 
}      
} 
em.commitTransaction(); 
+0

De cette façon, il fonctionne comme si vous l'aviez exclu. bon à savoir, gardera un oeil sur votre suggestion à l'avenir. Merci beaucoup! – Steve