Kamil K.

Kamil K. Senior Software
Engineer

Temat: Hibernate, jak zapisać dwa powiązane obiekty

Witajcie,

męczę się już ładny szmat czasu nad problemem zapisywania do bazy dwóch połączonych obiektów, tj. jeden posiada referencję @ManyToOne na drugi.
Oto mój applicationContext.xml
1. <?xml version="1.0" encoding="UTF-8"?>
2. <beans xmlns="http://www.springframework.org/schema/beans"
3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
4. xmlns:tx="http://www.springframework.org/schema/tx"
5. xsi:schemaLocation="http://www.springframework.org/schema/beans
6. http://www.springframework.org/schema/beans/spring-bea...
7. http://www.springframework.org/schema/tx
8. http://www.springframework.org/schema/tx/spring-tx.xsd">
9.
10.
11. <tx:annotation-driven transaction-manager="transactionManager" />
12.
13. <bean id="sessionFactory"
14. class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
15. <property name="dataSource" ref="dataSource" />
16.
17. <property name="annotatedClasses">
18. <list>
19. <value>pl.diagno.model.vo.Person</value>
20. <value>pl.diagno.model.vo.OrderGeneral</value>
21. <value>pl.diagno.model.vo.OrderDetails</value>
22. ... and others ...
23. </list>
24. </property>
25. <property name="hibernateProperties">
26. <props>
27. <prop key="show_sql">true</prop>
28. <prop key="dialect">org.hibernate.dialect.Oracle10gDialect</prop>
29. <prop key="hibernate.transaction.flush_before_completion">true</prop>
30. <prop key="hibernate.transaction.auto_close_session">true</prop>
31. <prop key="hibernate.use_sql_comments">true</prop>
32. <prop key="hibernate.connection.release_mode">auto</prop>
33.
34. </props>
35. </property>
36. </bean>
37.
38. <bean id="transactionManager"
39. class="org.springframework.orm.hibernate3.HibernateTransactionManager">
40. <property name="sessionFactory" ref="sessionFactory" />
41. </bean>
42.
43. <!-- DAO BEANS -->
44. <bean id="personDao" class="pl.diagno.dao.impl.PersonDAOImpl">
45. <property name="sessionFactory" ref="sessionFactory" />
46. </bean>
47.
48. <bean id="orderDetailsDao" class="pl.diagno.dao.impl.OrderDetailsDAOImpl">
49. <property name="sessionFactory" ref="sessionFactory" />
50. </bean>
51.
52. <bean id="orderGeneralDao" class="pl.diagno.dao.impl.OrderGeneralDAOImpl">
53. <property name="sessionFactory" ref="sessionFactory" />
54. </bean>
55.
56. <bean id="testDao" class="pl.diagno.dao.impl.TestDAOImpl">
57. <property name="sessionFactory" ref="sessionFactory" />
58. </bean>
59.
60. <!-- BO BEANS -->
61. <bean id="orderBo" class="pl.diagno.bo.impl.OrderBOImpl"> <!-- autowire="byName" -->
62. <property name="personDAO" ref="personDao" />
63. <property name="testDAO" ref="testDao" />
64. <property name="orderGeneralDAO" ref="orderGeneralDao" />
65. <property name="orderDetailsDAO" ref="orderDetailsDao" />
66. </bean>
67. </beans>

W OrderDetails jest odniesienie @ManyToOne do OrderGeneral.
Nie mogę zapisać OrderGeneral i powiązanego OrderDetails ponieważ Oracle rzuca wyjątek o braku parent key. Oto moja metoda:
1. @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
2. public void saveOrder(long personId, long clinicId, long testsId[]){
3.
4. OrderGeneral orderGeneral = new OrderGeneral();
5. orderGeneral.setPerson(personDAO.load(personId));
6. orderGeneralDAO.save(orderGeneral); // save orderGeneral
7.
8. for(int i = 0; i<testsId.length; i++){
9. OrderDetails orderDetails = new OrderDetails();
10. orderDetails.setOrderGeneral(orderGeneral); //set orderGeneral
11. orderDetails.setTest(testDAO.load(testsId[i]));
12. orderDetailsDAO.save(orderDetails); //save orderDetails
13. }
14. }

i wyjątek
java.sql.BatchUpdateException: ORA-02291: integrity constraint (DIAGNO.ORDERDETAILS_ORDERGENERAL_FK) violated - parent key not found
Czyli powinno być tak że najpierw w bazie zapisuje się orederGeneral, później jest on ustawiany jako pole w orderDetails i zapisywany jest również orderDetails. A niestety wszystko się wali na pierwszym kroku.
Miałem taki sam problem wcześniej, to znaczy chciałem zapisać Person razem z jego polem City. I nie dało się to zrobić za jednym razem. Musiałem "obejść" ten problem tak że w jednej formatce dodaję nowe miasto a w drugim dopiero osobę z załadowanym już, istniejącym w bazie miastem.
Aleksander Lech

Aleksander Lech Architekt rozwiązań

Temat: Hibernate, jak zapisać dwa powiązane obiekty

Jezeli masz relacje dwustronna to musisz z obu stron poustawiac referencje na obiektach. Np:

Child child = new Child();
Parent parent = new Parent();

child.setParent(parent);
parent.getChldren().add(child);

Mozna to tez zrobic za pomoca odpowiedniej konfiguracji kaskady.
Łukasz Żuchowski

Łukasz Żuchowski Software Wizard

Temat: Hibernate, jak zapisać dwa powiązane obiekty

Podpwiedzi brzmi: "Cascade"
Aleksander Lech

Aleksander Lech Architekt rozwiązań

Temat: Hibernate, jak zapisać dwa powiązane obiekty

Jezeli relacja jest jednostronna to musisz i tak na obu wywolac save albo jak podpowiada kolega miec kaskade w parencie na polu childreen :)
Kamil K.

Kamil K. Senior Software
Engineer

Temat: Hibernate, jak zapisać dwa powiązane obiekty

Dziękuję za odpowiedzi, ale takie podstawowe rzeczy już dawno sprawdziłem. Wszędzie jest ustawione CascadeType.ALL, próbowałem też {CascadeType.PERSIST, CascadeType.MERGE}.
Relacja jest jednostronna.Kamil Kuchta edytował(a) ten post dnia 02.06.10 o godzinie 18:05
Damian P.

Damian P. Starszy Programista
Java / JEE

Temat: Hibernate, jak zapisać dwa powiązane obiekty

Czy jesteś pewien, że transakcje działają prawdłowo?
Do jakiej klasy należy metoda: public void saveOrder()?
Czy jest to aplikacja www? Jeżeli tak, a ta klasa nie jest kontrolerem, to być może do applicationContext.xml powinieneś dodać wpis w stylu:
<context:component-scan base-package="twoj.pakiet.z.klasa.zawierajaca.ta.metode" />
Kamil K.

Kamil K. Senior Software
Engineer

Temat: Hibernate, jak zapisać dwa powiązane obiekty

Tego czy transakcje działają prawidłowo pewny nie jestem i jak dla mnie jest to jeden z głównych kandydatów w którym może tkwić problem.
saveOrder() jest częścią orderBO (jest wymieniony w pierwszym poście w applicationContext). Na początku moje bean'y BO dziedziczyły z bean'u transactionProxyBean ale znalazłem że to jest niby stare rozwiązanie i zastąpiłem go przez <tx:annotation-driven transaction-manager="transactionManager" />
Niestety skutek jest marny. Nic się nie zmieniło.
To nie jest webowa aplikacja. Beany tworzę sobie w fabryce w taki sposób:
orderBO = ((IOrderBO)context.getBean("orderBo"));
Ogólnie wszystko działa, problem jest właśnie z takim zapisem i to nie tylko z orderDetails i orderGeneral - tak jak wcześniej pisałem.
Nawet przy tym wcześniejszym problemie (z Person i City) nie korzystałem jeszcze z HibernateTemplate (tylko session) i transakcji, to problem był identyczny jak teraz z HibTempl i transakcjami.

Może jest to problem związany z Oraclem? Ciekawi mnie dlaczego przy starcie dostaję wiadomość że
INFO Dialect:151 - Using dialect: org.hibernate.dialect.Oracle9Dialect
skoro jak wół mam
<prop key="dialect">org.hibernate.dialect.Oracle10gDialect</prop>
i próbowałem też OracleDialect.
Ale z drugiej strony pisze że
INFO SettingsFactory:81 - RDBMS: Oracle, version: Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
INFO SettingsFactory:82 - JDBC driver: Oracle JDBC driver, version: 10.2.0.1.0
Ale pewnie to nie ma znaczenia...

Ciekawe jest też że za cholere nie mogę zobaczyć jakie SQLe idą do bazy. Mam ustawione
<prop key="show_sql">true</prop>
ale on sobie nic z tego nie robi. Dodałem log4j, log4j.properties wziąłem stąd
http://www.mkyong.com/hibernate/how-to-display-hiberna...
ale nie wyświetla SQLi. Dostaję tylko to co jest zwracane z bazy
TRACE LongType:122 - returning '1' as column: id5_1_
TRACE StringType:122 - returning 'Krakow' as column: name0_0_
TRACE StringType:122 - returning 'Strzykawa' as column: name5_1_
itd.....
Sebastian Kolski

Sebastian Kolski programista/DBA

Temat: Hibernate, jak zapisać dwa powiązane obiekty

A jak zakładałeś więzy integralności?
Czy DIAGNO.ORDERDETAILS_ORDERGENERAL_FK jest deferrable initially deferred?
Jeśli nie jest (a standardowo jest not deferrable i initially immediate), to aby nie było błędu musiał byś commitow'ać po wrzuceniu order zanim wrzucisz detale.
Kamil K.

Kamil K. Senior Software
Engineer

Temat: Hibernate, jak zapisać dwa powiązane obiekty

Nie wiedziałem jak było ale na pewno było domyślnie. Tabela teraz wygląda tak:

CREATE TABLE "ORDERDETAILS"
( "ID" NUMBER NOT NULL ENABLE,
"ORDER_GENERAL_ID" NUMBER,
"TEST_ID" NUMBER,
CONSTRAINT "ORDERDETAILS_PK" PRIMARY KEY ("ID") ENABLE,
CONSTRAINT "ORDERDETAILS_ORDERGENERAL_FK" FOREIGN KEY ("ORDER_GENERAL_ID")
REFERENCES "ORDERGENERAL" ("ID") DEFERRABLE INITIALLY DEFERRED ENABLE,
CONSTRAINT "ORDERDETAILS_TEST_FK" FOREIGN KEY ("TEST_ID")
REFERENCES "TEST" ("ID") ENABLE
)

I nic z tego :)
Wiem że tu chyba potrzeba cudotwórcy...
Wkleję cały wyjątek:
Exception in thread "AWT-EventQueue-0" org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: JDBC commit failed
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:660)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:394)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:117)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy31.saveOrder(Unknown Source)
at pl.diagno.gui.frames.NewOrderIntFrame$4.actionPerformed(NewOrderIntFrame.java:119)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:6263)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
at java.awt.Component.processEvent(Component.java:6028)
at java.awt.Container.processEvent(Container.java:2041)
at java.awt.Component.dispatchEventImpl(Component.java:4630)
at java.awt.Container.dispatchEventImpl(Container.java:2099)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
at java.awt.Container.dispatchEventImpl(Container.java:2085)
at java.awt.Window.dispatchEventImpl(Window.java:2475)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Caused by: org.hibernate.TransactionException: JDBC commit failed
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:130)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
... 33 more
Caused by: java.sql.SQLException: ORA-02091: transaction rolled back
ORA-02291: integrity constraint (DIAGNO.ORDERDETAILS_ORDERGENERAL_FK) violated - parent key not found

at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:283)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:278)
at oracle.jdbc.driver.T4C7Ocommoncall.receive(T4C7Ocommoncall.java:141)
at oracle.jdbc.driver.T4CConnection.doCommit(T4CConnection.java:523)
at oracle.jdbc.driver.PhysicalConnection.commit(PhysicalConnection.java:1119)
at org.hibernate.transaction.JDBCTransaction.commitAndResetAutoCommit(JDBCTransaction.java:139)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:115)
... 34 moreKamil Kuchta edytował(a) ten post dnia 03.06.10 o godzinie 15:03
Sebastian Kolski

Sebastian Kolski programista/DBA

Temat: Hibernate, jak zapisać dwa powiązane obiekty

Pokaż kod OrderGeneral, OrderDetails i orderGeneralDAO.save()
Jeśli np w OrderGeneral ma pk generowany, a w save robisz merge zamiast persista to orderGeneral ustawiany w orderDetails nie ma pk.
Sprawdzić co się dzieje można to na kilka sposobów. Uruchom program pod debugerem i sprawdzaj co jest wysyłane do zapisania w bazie, włącz logowanie sql'i, włącz tracowanie sesji oracle czy po prostu dodaje System.out.println który by pokazywał pk orderGeneral ustawiany w orderDetails. Można nawet usunąć ten constraint i sparwdzić co się zapisze w bazie.
Jeśli myślisz że błąd jest po stronie Oracle, to sprawdzenie tego też jest banalne. Podłącz się do bazy i spróbuj wykonać sql'e które myślisz, że są wysyłane i sprawdź czy się uda.Sebastian Kolski edytował(a) ten post dnia 03.06.10 o godzinie 15:11
Kamil K.

Kamil K. Senior Software
Engineer

Temat: Hibernate, jak zapisać dwa powiązane obiekty

OrderGeneral:
@Entity
public class OrderGeneral {

private long id;
private Date orderDate;
private Person person;
private Clinic clinic;

public OrderGeneral(){}

@Column
@Id
@GeneratedValue(generator="OrdGenSeq")
@SequenceGenerator(name="OrdGenSeq",sequenceName="ORDERGENERAL_SEQ", allocationSize=5)
public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

@Column(name="order_date")
public Date getOrderDate() {
return orderDate;
}

public void setOrderDate(Date orderDate) {
this.orderDate = orderDate;
}
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="person_id")
public Person getPerson() {
return person;
}

public void setPerson(Person person) {
this.person = person;
}
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="clinic_id")
public Clinic getClinic() {
return clinic;
}

public void setClinic(Clinic clinic) {
this.clinic = clinic;
}
}

OrderDetails:
@Entity
public class OrderDetails {

private long id;
private OrderGeneral orderGeneral;
private Test test;

public OrderDetails(){}
@Column
@Id
@GeneratedValue(generator="OrdDetSeq")
@SequenceGenerator(name="OrdDetSeq",sequenceName="ORDERDETAILS_SEQ", allocationSize=5)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="order_general_id")
public OrderGeneral getOrderGeneral() {
return orderGeneral;
}

public void setOrderGeneral(OrderGeneral orderGeneral) {
this.orderGeneral = orderGeneral;
}

@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="test_id")
public Test getTest() {
return test;
}

public void setTest(Test test) {
this.test = test;
}
}

a to save z parametryzowanej klasy po której dziedziczą wszystkie DAO
public void save(final E entity) {
hibernateTemplate.saveOrUpdate(entity);
}

Id jest pobierane poprawnie.
System.out.println(orderDetails.getOrderGeneral().getId()) wypisuje poprawne ID.

Udało mi się ustawić logowanie w log4j. Idą takie sqle które powinny iść:
insert into OrderGeneral (person_id, clinic_id, order_date, id) values (?, ?, ?, ?)
insert into OrderDetails (order_general_id, test_id, id) values (?, ?, ?)

"...a w save robisz merge zamiast persista to..." - nie rozumiem? CascadeType.ALL mam tylko ustawione w modelu danych (tak jak widać powyżej), a w żadnej metodzie tego nie ustawiam. Może czegoś nie wiem że powinienem zrobić?

Próbowałem wysyłać sqle ręcznie i działa.

insert into OrderGeneral(person_id, clinic_id, order_date) values(2, 2, (to_date('2003/05/03 21:02:44', 'yyyy/mm/dd hh24:mi:ss')));
insert into OrderDetails(order_general_id, test_id) values(74, 1);

tylko że tu na sztywno wpisuję jakie id ma OrderGeneral.
Zauważyłem że gdy coś dodaję do bazy z poziomu mojej aplikacji to id "czegoś" za każdym razem zwiększa się o 2 zamiast o jeden.
Chodzi o to że uruchomienie
System.out.println(orderDetails.getOrderGeneral().getId())
przy próbie zapisu saveOrder() raz wypisze 76 a później 78, 80... Może orderDetails chce namierzyć orderGeneral po 77 a on ma już 78?Kamil Kuchta edytował(a) ten post dnia 03.06.10 o godzinie 18:22
Sebastian Kolski

Sebastian Kolski programista/DBA

Temat: Hibernate, jak zapisać dwa powiązane obiekty

Kamil Kuchta:
"...a w save robisz merge zamiast persista to..." - nie rozumiem?

Myślałem, że używasz standardowego JPA (javax.persistance.EntityManager.persist()/merge()).

W jakim celu masz w OrderDetails CascadeType.ALL przy OrderGeneral? To znaczy dlaczego operacje na detalu miały by się propagować na order?
Spróbuj tego nie ustawiać.

Jak nie pomoże to wywal ten constraint i sprawdź co się zapisze w bazie.
Kamil K.

Kamil K. Senior Software
Engineer

Temat: Hibernate, jak zapisać dwa powiązane obiekty

Usunięcie CascadeType.ALL z OrderDetails nic nie dało.

Ale udało się zidentyfikować problem dzięki Twojej radzie!
Usunąłem constraint i zapisuje się tak jak podejrzewałem w poprzednim poście.
Załóżmy że ostatni id OrderGeneral w bazie jest 80.
Po dokonaniu zapisu jest tak:
ID OrderGeneral to 82
FK na w OrderDetails na OrderGeneral to 81

Wielkie dzięki za radę! Będę próbował teraz się dowiedzieć dlaczego generuje id co 2 a nie co 1.
Oczywiście gdyby ktoś znał odpowiedź to bardzo chętnie przyjmę :)
Tu są logi które idą przy zapisywaniu. Nic niepokojącego tam nie widać.
http://student.agh.edu.pl/~kamilk/diag/sqle.txt
Kamil K.

Kamil K. Senior Software
Engineer

Temat: Hibernate, jak zapisać dwa powiązane obiekty

Do każdego PK mam trigger
create or replace TRIGGER "TR_ORDERGENERAL_ID"
BEFORE
insert on "ORDERGENERAL"
for each row
begin
select "ORDERGENERAL_SEQ".nextval into :NEW.ID from dual;
end;

a że z logów wynika że hibernate również robi select ORDERGENERAL_SEQ.nextval from dual to zmieniłem w triggerze "ORDERGENERAL_SEQ".currval (z nextval). No i skutek jest dobry, id OrderGeneral zwiększa się o 1, to samo np. przy dodawaniu nowej osoby, też zwiększa się o jeden. Ale jest problem przy OrderDetails których zapisuje się kilka (więcej niż jedno) przy każdej transakcji. Tu już krzyczy że unique constraint w OrderDetails. A dziwne bo hibernate robi:
select ORDERGENERAL_SEQ.nextval from dual
select test0_.id as id3_1_, test0_.name as name3_1_, ............
select ORDERDETAILS_SEQ.nextval from dual
select test0_.id as id3_1_, test0_.name as name3_1_,...........
select ORDERDETAILS_SEQ.nextval from dual
select test0_.id as id3_1_, test0_.name as name3_1_, ..........
select ORDERDETAILS_SEQ.nextval from dual
insert into OrderGeneral (person_id, clinic_id, order_date, id) values (?, ?, ?, ?)
insert into OrderDetails (test_id, order_general_id, id) values (?, ?, ?)
insert into OrderDetails (test_id, order_general_id, id) values (?, ?, ?)
insert into OrderDetails (test_id, order_general_id, id) values (?, ?, ?)

Ale może powinno być tak?

select ORDERGENERAL_SEQ.nextval from dual
select test0_.id as id3_1_, test0_.name as name3_1_, ............
select test0_.id as id3_1_, test0_.name as name3_1_,...........
select test0_.id as id3_1_, test0_.name as name3_1_, ..........

insert into OrderGeneral (person_id, clinic_id, order_date, id) values (?, ?, ?, ?)
select ORDERDETAILS_SEQ.nextval from dual
insert into OrderDetails (test_id, order_general_id, id) values (?, ?, ?)
select ORDERDETAILS_SEQ.nextval from dual
insert into OrderDetails (test_id, order_general_id, id) values (?, ?, ?)
select ORDERDETAILS_SEQ.nextval from dual
insert into OrderDetails (test_id, order_general_id, id) values (?, ?, ?)
Sebastian Kolski

Sebastian Kolski programista/DBA

Temat: Hibernate, jak zapisać dwa powiązane obiekty

Z kodu wynika, że zarówno w OrderGeneral jak i OrderDetails masz PK generowane przez ORM'a. To że masz dodatkowo triggera w bazie, który podmienia wartość PK przy zapisie w tabelach jest przyczyną problemów.

Ciąg zdarzeń jest mniej więcej następujący:
przed zapisem instancji OrderGeneral w bazie Hibernate generuje dla niej PK (powiedzmy X)
zapisujesz obiekt do bazy
w czasie zapisu trigger zmienia PK z X na Y
Hibernate o tym nie wie i myśli, że ma w bazie zapisany OrderGeneral z PK X
używa go przy próbie zapisu OrderDetails co oczywiście powoduje błąd

Wywalenie triggerów generujących PK rozwiąże problem.
Jeśli one muszą tam być (np inne aplikacje używają tych tabel i dla poprawnego działania wymagają tych triggerów), to możesz do nich dodać sprawdzanie czy PK jest przekazywane i generowanie nowego tylko w przypadku braku.
Kamil K.

Kamil K. Senior Software
Engineer

Temat: Hibernate, jak zapisać dwa powiązane obiekty

Dzięki wielkie!
Na razie działa ;)

Następna dyskusja:

Czy ktos wie jak zmapowac I...




Wyślij zaproszenie do