2013-08-26 11 views
5

Jestem całkiem nowy w Hibernate i próbowałem ustalić, co on zrobi dla ciebie i co wymaga, abyś zrobił.Hibernacja, automatycznie utrzymywane obiekty zależne

Duży dotyczy obiektu, który ma osoby pozostające na stałe w bazie danych. Na przykład, mam obiekt projektu, który zawiera pole producenta, które akceptuje obiekt producenta jako jego wartość. W bazie danych mam tabelę produktów z kolumną mfr_id, która jest odniesieniem do tabeli producentów (dość typowa, jednokierunkowa relacja jeden-do-wielu).

Jeśli producent przypisany do obiektu produktu odnosi się do tego, który jest już w bazie danych, nie ma problemu. Jednak gdy próbuję zapisać lub zaktualizować obiekt, który odwołuje się do producenta, który nie został jeszcze utrwalony, operacja kończy się niepowodzeniem z wyjątkiem.

Wyjątek w wątku „Application” org.hibernate.TransientObjectException: obiekt odwołuje niezapisaną przemijające wystąpienie - zachowaj przemijające wystąpienie przed płukaniem

mogę oczywiście ręcznie sprawdzić stan producenta produktu przez sprawdzanie, czy pole identyfikatora ma wartość NULL i zapisanie go, jeśli jest, ale wydaje się, że jest to kłopotliwe rozwiązanie. Czy wsparcie Hibernate automatycznie utrzymuje się na utrzymaniu, jeśli zależne pytanie nie jest jeszcze utrzymane? Jeśli tak, w jaki sposób włączyć to zachowanie? Używam wersji Hibernate z Netbeans (3.5, jak sądzę) i wbudowanych adnotacji do określania zachowania odwzorowania. Poniżej znajdują się moje klasy produktów i producentów, ograniczane do części, które obsługują zależność. (Produkt rozciąga można sprzedać który mapuje do PUM tabeli, używając dołączył jako strategii spadkowego To, że tabela, która zawiera klucz podstawowy, który identyfikuje produkt)

@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; 
    } 
} 

na utrzymaniu Producent

@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; 
    } 
} 

Aktualizacja: próbowałem następujących z this question, ale nadal otrzymuję wyjątek obiektu przejściowe.

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

Sprawdziłem też, jaka wersja Hibernate jest w zestawie z Netbeans, to 3.2.5

UPDATE 2: okazało się, że po pozornie wydaje się działać jak chciałem.

@ManyToOne (fetch = FetchType.EAGER, cascade = CascadeType.ALL) 

Podejrzewam jednak, że nie jest to typ kaskady, którego naprawdę chcę. Jeśli usuwam produkt, nie sądzę, aby usunięcie jego powiązanego producenta było działaniem prawidłowym, co według mnie stanie się teraz.

Próbowałem utworzyć typ kaskadowy, który składał się z wszystkich dostępnych typów, ale to też nie działało. Wystąpił ten sam wyjątek, gdy próbowałem zapisać produkt, który był powiązany z niezapisanym producentem.

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

Widziałem CascadeType.SAVE_UPDATE wspomniano w kilku miejscach, ale to tryb nie wydają się być dostępne w wersji Hibernate, że pochodzi z Netbeans.

Odpowiedz

7

Musisz przyjrzeć się operacjom kaskadowym; ten typ operacji pozwala zarządzać cyklem życia wewnętrznego obiektu, respektując jego rodzica.

@ManyToOne(cascade) jeśli używasz Session.persist() operację lub [email protected] jeśli używasz nie WZP funkcję Session.saveOrUpdate().

Jest to tylko przykład, do pełnego punktu doc ​​here

Dla kodu, jeśli chcesz, aby automatycznie zapisać Manufacturer podczas zapisywania Project zastosowanie:

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

lub

@Cascade(CascadeType.PERSIST) 
+0

Próbowałem twojej sugestii, ale wciąż mam ten sam wyjątek dotyczący obiektów przejściowych, kiedy próbuję zapisać obiekt. Próbowałem również podejście sugerowane w http://stackoverflow.com/questions/9032998/hibernate-cascades-object-references-an-unsaved-transient-instance-save-the \t @ManyToOne (fetch = FetchType.EAGER, kaskada = {CascadeType.PERSIST, CascadeType.MERGE}), ale to nie zadziałało ani – GordonM

+0

czy używasz saveOrUpdate()? w tym przypadku potrzebujesz 'org.hibernate.annotation. @ Cascade (CascadeType.SAVE_UPDATE)' –

+0

W tej chwili używam tylko save(). Przyjrzę się innym opcjom, kiedy wrócę dziś do domu. – GordonM