2013-08-26 2 views
5

Je suis assez nouveau pour Hibernate et j'ai essayé de déterminer ce qu'il va faire pour vous et ce que cela vous demande de faire.Hibernate, persiste automatiquement les objets dépendants

Un gros problème concerne un objet qui a des dépendances qui n'existent pas encore dans la base de données. Par exemple, j'ai un objet Project qui inclut un champ Manufacturer qui accepte un objet Manufacturer comme valeur. Dans la base de données, j'ai une table de produits avec une colonne mfr_id qui est une référence à la table des fabricants (une relation un-à-plusieurs unidirectionnelle assez typique).

Si le fabricant affecté à l'objet produit correspond à celui qui est déjà dans la base de données, cela signifie qu'il n'y a aucun problème. Toutefois, lorsque j'essaie d'enregistrer ou de mettre à jour un objet qui référence un fabricant qui n'a pas encore été conservé, l'opération échoue avec une exception.

Exception dans le thread « Application » org.hibernate.TransientObjectException: objet référence une instance transitoire non enregistré - sauvegarder l'instance transitoire avant le rinçage

Je peux vérifier bien sûr manuellement l'état du fabricant du produit par voir si son champ d'identification est nul et l'enregistrer si c'est le cas, mais cela semble être une solution encombrante. Est-ce que Hibernate supporte automatiquement les dépendants persistants si la dépendance en question n'est pas encore persistante? Si oui, comment puis-je activer ce comportement? J'utilise la version d'Hibernate fournie avec Netbeans (3.5, je crois) et des annotations en ligne pour spécifier le comportement de mappage. Voici mes classes de produits et de fabricants, réduites aux parties qui traitent la dépendance. (Étend Produit vendable qui associe à une table vendable, en utilisant REJOINT comme la stratégie d'héritage Il est cette table qui contient la clé primaire qui identifie le produit)

@Entity 
@Table (
     name="products", 
     schema="sellable" 
) 
public abstract class Product extends Sellable { 
    private Manufacturer      manufacturer; 

    @ManyToOne (fetch = FetchType.EAGER) 
    @JoinColumn (name = "mfr_id") 
    public Manufacturer getManufacturer() { 
     return this.manufacturer; 
    } 

    /** 
    * 
    * @param manufacturer 
    */ 
    public Product setManufacturer (Manufacturer manufacturer) { 
     this.manufacturer = manufacturer; 
     return this; 
    } 
} 

La personne à charge du fabricant

@Entity 
@Table (
     name="manufacturers", 
     schema="sellable", 
     uniqueConstraints = @UniqueConstraint(columnNames="mfr_name") 
) 
public class Manufacturer implements Serializable { 
    private Integer   mfrId  = null; 
    private String   mfrName  = null; 

    @Id 
    @SequenceGenerator (name = "manufacturers_mfr_id_seq", sequenceName = "sellable.manufacturers_mfr_id_seq", allocationSize = 1) 
    @GeneratedValue (strategy = GenerationType.SEQUENCE, generator = "manufacturers_mfr_id_seq") 
    @Column (name="mfr_id", unique=true, nullable=false) 
    public Integer getMfrId() { 
     return mfrId; 
    } 

    private Manufacturer setMfrId (Integer mfrId) { 
     this.mfrId = mfrId; 
     return this; 
    } 

    @Column(name="mfr_name", unique=true, nullable=false, length=127) 
    public String getMfrName() { 
     return mfrName; 
    } 

    public Manufacturer setMfrName (String mfrName) { 
     this.mfrName = mfrName; 
     return this; 
    } 
} 

MISE À JOUR: I essayé le suivant de this question, mais je reçois toujours l'exception de l'objet transitoire.

@ManyToOne (fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE}) 

J'ai aussi vérifié quelle version d'Hibernate est livré avec Netbeans, il est 3.2.5

MISE À JOUR 2: Je trouve que ce qui suit semble fonctionner apparemment comme je le voulais. Cependant, je soupçonne que ce n'est pas le type de cascade que je veux vraiment. Si je supprime un produit, je ne pense pas que la suppression de son fabricant associé est l'action correcte, ce qui, je crois, se produira maintenant.

J'ai essayé de créer un type de cascade qui comprenait tous les types disponibles, mais cela ne fonctionnait pas non plus. J'ai eu la même exception quand j'ai essayé de sauvegarder un produit auquel un fabricant non enregistré était associé.

@ManyToOne (fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}) 

Je l'ai vu CascadeType.SAVE_UPDATE mentionné dans plusieurs endroits, mais ce mode ne semble pas être disponible dans la version d'Hibernate qui vient avec Netbeans.

Répondre

7

Vous devez regarder les opérations en cascade; Ce type d'opération vous permet de gérer le cycle de vie de l'objet interne en respectant son parent.

@ManyToOne(cascade) si vous utilisez Session.persist() opération ou [email protected] si vous utilisez ne fonctionne pas JPA Session.saveOrUpdate().

Ceci est juste un exemple, pour le point doc complet here

Pour votre code, si vous souhaitez enregistrer automatiquement Manufacturer lors de l'enregistrement Project utilisation:

@ManyToOne (fetch = FetchType.EAGER, cascade = {javax.persistence.CascadeType.PERSIST}) 
@JoinColumn (name = "mfr_id") 
public Manufacturer getManufacturer() { 
    return this.manufacturer; 
} 

ou

@Cascade(CascadeType.PERSIST) 
+0

J'ai essayé votre suggestion, mais je reçois toujours la même exception à propos des objets transitoires lorsque j'essaie de sauvegarder l'objet. J'ai également essayé l'approche suggérée dans http://stackoverflow.com/questions/9032998/hibernate-cascades-object-references-an-unsaved-transient-instance-save-the of \t @ManyToOne (fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE}) mais cela n'a pas fonctionné non plus – GordonM

+0

utilisez-vous saveOrUpdate()? Dans ce cas, vous avez besoin de 'org.hibernate.annotation. @ Cascade (CascadeType.SAVE_UPDATE)' –

+0

Pour l'instant, je n'utilise que save(). Je vais regarder d'autres options quand je rentre à la maison ce soir. – GordonM

Questions connexes