Domanda

Ho le seguenti classi di entità Hibernate annotate:

@Entity
public class Cat {
    @Column(name = "ID") @GeneratedValue(strategy = GenerationType.AUTO) @Id
    private Long id;

    @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<Kitten> kittens = new HashSet<Kitten>();

    public void setId(Long id) { this.id = id; }
    public Long getId() { return id; }
    public void setKittens(Set<Kitten> kittens) { this.kittens = kittens; }
    public Set<Kitten> getKittens() { return kittens; }
}

@Entity
public class Kitten {
    @Column(name = "ID") @GeneratedValue(strategy = GenerationType.AUTO) @Id
    private Long id;

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Cat cat;

    public void setId(Long id) { this.id = id; }
    public Long getId() { return id; }
    public void setCat(Cat cat) { this.cat = cat; }
    public Cat getCat() { return cat; }
}

La mia intenzione: ecco un bidirezionale uno-a-molti / molti-a-uno tra Gatto e gattino, con Kitten è il "lato possedere".

Quello che voglio che accada è quando creo un nuovo gatto, seguito da un nuovo gattino riferimento al gatto, Set di gattini sul mio gatto dovrebbe contenere il nuovo gattino . Tuttavia, questo non accade nella seguente test:

@Test
public void testAssociations()
{
    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    Transaction tx = session.beginTransaction();

    Cat cat = new Cat();
    session.save(cat);

    Kitten kitten = new Kitten();
    kitten.setCat(cat);
    session.save(kitten);

    tx.commit();

    assertNotNull(kitten.getCat());
    assertEquals(cat.getId(), kitten.getCat().getId());
    assertTrue(cat.getKittens().size() == 1); // <-- ASSERTION FAILS
    assertEquals(kitten, new ArrayList<Kitten>(cat.getKittens()).get(0));
}

Anche dopo ri-interrogare il Gatto, il set è ancora vuota:

// added before tx.commit() and assertions
cat = (Cat)session.get(Cat.class, cat.getId());

mi aspetto troppo da Hibernate qui? O è l'onere su di me per gestire la raccolta me stesso? Il (Annotazioni) Documentazione non fa alcuna indicazione che ho bisogno di creare metodi di convenienza addTo* / removeFrom* sul mio oggetto padre.

Qualcuno può per favore mi illumini su ciò che le mie aspettative dovrebbero essere da Hibernate con questo rapporto? Oppure, se non altro, mi puntare alla corretta documentazione di Hibernate che mi dice cosa devo essere in attesa di accadere qui.

Che cosa devo fare per fare il genitore Collection contiene automaticamente il bambino Entity?

È stato utile?

Soluzione

Non aggiungerà automaticamente. È necessario aggiungere voi stessi.

Non vorrei chiamare direttamente Kitten.setCat() neanche. Il modello tipico per questo è di mettere un metodo in Cat come:

public void addKitten(Kitten kitten) {
  if (kittens == null) {
    kittens = new HashSet<Kitten>();
  }
  kittens.add(kitten);
  kitten.setCat(this);
}

e poi semplicemente chiamare:

cat.addKitten(kitten);

Altri suggerimenti

Quando si lavora con le associazioni bi-direzionale, si deve gestire entrambi i lati del "link" ed è molto comune l'uso di metodi di gestione collegamento difensive per che, come suggerito da @ Cletus. Dalla documentazione Hibernate Nucleo:

  

1.2.6 . rapporti di lavoro bidirezionali

     

In primo luogo, tenere presente che Hibernate   non pregiudica il normale semantica di Java.   Come abbiamo fatto a creare un collegamento tra un   Persona e un evento nel   esempio unidirezionale? Si aggiunge un   istanza di eventi per la raccolta di   riferimenti di eventi, di un'istanza di   Persona. Se si vuole fare questo link   bi-direzionale, si deve fare il   stesso sull'altro lato aggiungendo un   Persona di riferimento per la raccolta di   un evento. Questo processo di impostazione"   il link da entrambe le parti" è assolutamente   necessario con collegamenti bidirezionali.

     

Molti sviluppatori di programmare in difesa   e creare metodi di gestione puntano a   impostate correttamente entrambi i lati (per esempio,   in persona):

protected Set getEvents() {
    return events;
}

protected void setEvents(Set events) {
    this.events = events;
}

public void addToEvent(Event event) {
    this.getEvents().add(event);
    event.getParticipants().add(this);
}

public void removeFromEvent(Event event) {
    this.getEvents().remove(event);
    event.getParticipants().remove(this);
}
     

I metodi get e set per la   collezione sono ora protetti. Questo   permette classi dello stesso pacchetto e   sottoclassi di accedere ancora il   metodi, ma evita tutti gli altri   possano modificare le collezioni   direttamente. Ripetere i passaggi per la   raccolta sul lato opposto.

Altri riferimenti

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top