2009-07-09 14 views
1

Je rencontre un problème lors de l'implémentation d'une relation parent/enfant bidirectionnelle utilisant hibernate 3. Le parent, dans ce cas, appartient à la classe ReportCriteria. L'enfant est de classe PkVisit. J'ai collé mes fichiers de configuration d'hibernation ainsi que les objets java sous-jacents ci-dessous.Problème parent/enfant bidirectionnel Hibernate

configuration ReportCriteria:

<hibernate-mapping package="org.fstrf.masterpk.domain"> 
<class name="ReportCriteriaBean" table="masterPkReportCriteria"> 

    <id name="id" column="id"> 
     <generator class="org.hibernate.id.IncrementGenerator" /> 
    </id> 

    <bag name="pkVisits" table="masterPkWeeks" cascade="all-delete-orphan" inverse="true"> 
     <key column="runId"/> 
     <one-to-many class="PkVisit"/> 
    </bag> 
</class> 
</hibernate-mapping> 

ReportCriteria haricot:

public class ReportCriteriaBean { 

private Integer id; 

private List<PkVisit> pkVisits = LazyList.decorate(new ArrayList(), FactoryUtils.instantiateFactory(PkVisit.class)); 

public Integer getId() { 
    return id; 
} 
public void setId(Integer id) { 
    this.id = id; 
} 

public List<PkVisit> getPkVisits() { 
    return pkVisits; 
} 

public void setPkVisits(List<PkVisit> pkVisits) { 
    this.pkVisits = pkVisits; 
} 

} 

PkVisit Configuration:

<hibernate-mapping package="org.fstrf.masterpk.domain"> 
<class name="PkVisit" table="masterPkWeeks"> 
    <id name="id" column="id"> 
     <generator class="org.hibernate.id.IncrementGenerator" /> 
    </id> 

    <many-to-one name="reportCriteriaBean" class="ReportCriteriaBean" column="runid" not-null="true" /> 

    <property name="week" column="week" /> 

</class> 
</hibernate-mapping> 

PkVisit Bean:

public class PkVisit { 
private Integer id; 

private ReportCriteriaBean reportCriteriaBean; 

private Integer week; 

public Integer getId() { 
    return id; 
} 
public void setId(Integer id) { 
    this.id = id; 
} 
public ReportCriteriaBean getReportCriteriaBean() { 
    return reportCriteriaBean; 
} 
public void setReportCriteriaBean(ReportCriteriaBean reportCriteriaBean) { 
    this.reportCriteriaBean = reportCriteriaBean; 
} 
public Integer getWeek() { 
    return week; 
} 
public void setWeek(Integer week) { 
    this.week = week; 
} 
} 

Le problème se produit lorsque j'essaie d'enregistrer une instance de ReportCriteria, qui, en raison de la cascade devrait également enregistrer tous les PkVisits enfants. Toutefois, lorsque la sauvegarde est appelée à l'aide

hibernateTemplate.saveOrUpdate(reportCriteria); 

L'erreur suivante est générée:

org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: org.fstrf.masterpk.domain.PkVisit.reportCriteriaBean; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: org.fstrf.masterpk.domain.PkVisit.reportCriteriaBean 

Lorsque j'enregistre un critère de rapport qui ne contient pas PkVisits alors tout fonctionne comme j'attendre, mais dès que tous les éléments sont dans la liste pkVisits du bean ReportCriteria les erreurs se produisent.

SOLUTION EDIT:

Mon problème était que je ne mettre explicitement le parent (ReportCriteriaBean) chez les enfants (PkVisits). Je réglé le problème en éditant mon PkVisits setter de la manière suivante:

public void setPkVisits(List<PkVisit> pkVisits) { 
    this.pkVisits = pkVisits; 
    for(PkVisit visit : pkVisits){ 
     visit.setReportCriteriaBean(this); 
    } 
} 

Répondre

2

Il semble que vous ne créez pas la lien bidirectionnel dans Java correctement. Je recommande de créer une méthode add sur ReportCriteriaBean; quelque chose à l'effet de:

public boolean add(PkVisit pkVisit) { 
    boolean added = false; 
    added = getPkVisits().add(pkVisit); 
    if (added) { 
     pkVisit.setReportCriteriaBean(this); 
    } 
    return added; 
} 

L'erreur indique que vous ne pouvez pas enregistrer PkVisit si son ReportCriteriaBean est nulle. Le code ci-dessus, je pense, est votre lien manquant. Si vous allez cette route, vous ajoutez simplement le PkVisit à ReportCriteriaBean avant de persister les critères de rapport et tout devrait bien se passer.

De plus, voici un lien vers la documentation de mise en veille prolongée sur ce sujet, section 21.2

+0

Vous étiez raison de dire que la ReportCriteriaBean était nulle, mais à cause de la façon dont la liste des PkVisits était réglée cette fonction ajouter lui-même fait ne fonctionne pas. J'ai modifié mon message original pour indiquer le changement exact que j'ai fait. Merci! – TimmyJ

0

Vérifiez si le PkVisit est généré ok, avant l'appel saveOrUpdate().

Ensuite, vous devrez peut-être aggressif reportCriteriaBean/pkVisits où vous avez la session de mise en veille prolongée, avant d'y accéder où vous n'avez pas la session mise en veille prolongée:

Hibernate.initialize(reportCriteriaBean.getPkVisits());