Hallo zusammen,
ich verwende Hibernate in Zusammenhang mit EJB 3.0, JBoss 4.0.4 und MySQL 5.0.22. Als Beispiel habe ich zwei Objekte/Klassen (Cruise.java, Reservation.java) die in einer cascadierten One-To-Many-Relation zueinander stehen. Als initiale Befüllung werden ein Cruise-Objekt und zwei Reservation-Objekte in die Datenbank geschrieben (Persist). Versuche ich nun ein weiteres Reservation-Objekt der Liste der Reservation-Objekte hinzuzufügen (Merge), sehe ich im Server-Logfile, dass ein Insert-Statement für das betreffende Objekt erzeugt wird, das Objekt in der Datenbank als Row mit PK erscheint, jedoch im Objekt der PK nicht aktualisiert wird. Versuch man nun anschliessend in der gleichen Session ein weiteres Reservation-Objekt hinzuzufügen, wird das vorherige, weil der PK nicht aktualisert wurde, wieder gespeichert. Was mache ich falsch? Ich habe zu diesem Thema nichts in der Hibernate-Dokumentation gefunden. Danke im voraus. Anbei der Quellcode der einzelnen Klassen und der Ausschnitt der Server-Logs.
Cruise.java
Code:
@Entity
@Table(name = "CRUISE")
public class Cruise
{
private int _id;
private String _name = "";
private int _shipId;
private Collection<Reservation> _reservations = new ArrayList<Reservation>();
@Id
@GeneratedValue
@Column(name = "ID")
public int getId()
{
return _id;
}
public void setId(int pk)
{
_id = pk;
}
@Column(name = "NAME")
public String getname()
{
return _name;
}
public void setName(String name)
{
_name = name;
}
@Column(name = "SHIPID")
public int getShipId()
{
return _shipId;
}
public void setShipId(int id)
{
_shipId = id;
}
@OneToMany(mappedBy = "cruise", cascade={ CascadeType.ALL })
public Collection<Reservation> getReservations()
{
return _reservations;
}
public void setReservations(Collection<Reservation> reservations)
{
_reservations = reservations;
}
@Transient
public boolean addReservation(Reservation reservation){
reservation.setCruise(this);
boolean result = _reservations.add(reservation);
return result;
}
Reservation.java
Code:
@Entity
@Table(name = "RESERVATION")
public class Reservation
{
private int _id;
private String _date = "";
private String _amount = "";
private Cruise cruise;
public Reservation(){};
public Reservation(Cruise cr) {cruise = cr;}
@Id
@GeneratedValue
@Column(name = "ID")
public int getId()
{
return _id;
}
public void setId(int pk)
{
_id = pk;
}
@Column(name = "DATE")
public String getDate()
{
return _date;
}
public void setDate(String date)
{
_date = date;
}
@Column(name = "AMOUNT")
public String getAmount()
{
return _amount;
}
public void setAmount(String amount)
{
_amount = amount;
}
@ManyToOne
@JoinColumn(name = "CRUISE_ID")
public Cruise getCruise()
{
return cruise;
}
public void setCruise(Cruise cr)
{
cruise = cr;
}
Testprocedur
Code:
// very simple example
// 1. create one 'cruise' object and some 'reservation' objects
Cruise cruise = new Cruise();
cruise.setName( "Titanic" );
cruise.setShipId( 355 );
System.out.println("create object 'Cruise' ...");
Reservation reservation1 = new Reservation();
reservation1.setDate( "09.08.2006" );
reservation1.setAmount( "5000" );
reservation1.setCruise(cruise);
System.out.println("create 1st object 'Reservation' ...");
Reservation reservation2 = new Reservation();
reservation2.setDate( "10.08.2006" );
reservation2.setAmount( "6000" );
reservation2.setCruise(cruise);
System.out.println("create 2nd object 'Reservation' ...");
Collection<Reservation> reservations = new ArrayList<Reservation>();
reservations.add(reservation1);
reservations.add(reservation2);
System.out.println("add 'Reservation' objects to list ...");
cruise.setReservations(reservations);
System.out.println("set 'Reservation' list to 'Cruise' object ...");
// 2. insert 'cruise' object into databases
entityManager.persist(cruise);
System.out.println("insert object 'Cruise' to database ...");
System.out.println("primary key of persisted object 'Cruise' = '" + cruise.getId() + "' ...");
for ( int i = 0 ; i < 5 ; i++ ) {
Reservation reservation = new Reservation();
reservation.setDate( "11.08.2006" );
reservation.setAmount( new Integer(i).toString() );
cruise.addReservation(reservation);
System.out.println("modify 'Reservation' list : add new object 'Reservation' to 'Reservation' list ...");
entityManager.merge(cruise);
System.out.println("modify 'Reservation' list : PKs of persistent objects 'Reservation' ...");
for ( Reservation res : cruise.getReservations() ) {
System.out.println("modify 'Reservation' list : PK of object 'Reservation' = '" + res.getId() + "' ..." );
}
System.out.println("update object 'Cruise' in database ...");
}
JBoss Logfile
Code:
2006-08-17 10:13:56,770 INFO [STDOUT] insert object 'Cruise' to database ...
2006-08-17 10:13:56,770 INFO [STDOUT] primary key of persisted object 'Cruise' = '1' ...
2006-08-17 10:13:56,770 INFO [STDOUT] modify 'Reservation' list : create 3rd object 'Reservation' ...
2006-08-17 10:13:56,770 INFO [STDOUT] modify 'Reservation' list : add new object 'Reservation' to 'Reservation' list ...
2006-08-17 10:13:56,771 DEBUG [org.hibernate.impl.SessionImpl] opened session at timestamp: 4734166781014016
2006-08-17 10:13:56,771 DEBUG [org.hibernate.jdbc.JDBCContext] TransactionFactory reported no active transaction; Synchronization not registered
2006-08-17 10:13:56,771 DEBUG [org.hibernate.ejb.AbstractEntityManagerImpl] Looking for a JTA transaction to join
2006-08-17 10:13:56,771 DEBUG [org.hibernate.jdbc.JDBCContext] successfully registered Synchronization
2006-08-17 10:13:56,771 DEBUG [org.hibernate.ejb.AbstractEntityManagerImpl] Looking for a JTA transaction to join
2006-08-17 10:13:56,771 DEBUG [org.hibernate.ejb.AbstractEntityManagerImpl] Transaction already joined
2006-08-17 10:13:56,776 DEBUG [org.hibernate.loader.Loader] loading entity: [de.finnrw.elba.server.ejb.test.Cruise#1]
2006-08-17 10:13:56,789 DEBUG [org.hibernate.jdbc.AbstractBatcher] about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
2006-08-17 10:13:56,789 DEBUG [org.hibernate.jdbc.ConnectionManager] opening JDBC connection
2006-08-17 10:13:56,790 DEBUG [org.hibernate.SQL] select cruise0_.ID as ID7_1_, cruise0_.NAME as NAME7_1_, cruise0_.SHIPID as SHIPID7_1_, reservatio1_.CRUISE_ID as CRUISE
4_3_, reservatio1_.ID as ID3_, reservatio1_.ID as ID9_0_, reservatio1_.DATE as DATE9_0_, reservatio1_.AMOUNT as AMOUNT9_0_, reservatio1_.CRUISE_ID as CRUISE4_9_0_ from CR
UISE cruise0_ left outer join RESERVATION reservatio1_ on cruise0_.ID=reservatio1_.CRUISE_ID where cruise0_.ID=?
2006-08-17 10:13:56,791 DEBUG [org.hibernate.jdbc.AbstractBatcher] about to open ResultSet (open ResultSets: 0, globally: 0)
2006-08-17 10:13:56,793 DEBUG [org.hibernate.loader.Loader] result row: EntityKey[de.finnrw.elba.server.ejb.test.Reservation#1], EntityKey[de.finnrw.elba.server.ejb.test.
Cruise#1]
2006-08-17 10:13:56,805 DEBUG [org.hibernate.loader.Loader] found row of collection: [de.finnrw.elba.server.ejb.test.Cruise.reservations#1]
2006-08-17 10:13:56,817 DEBUG [org.hibernate.loader.Loader] result row: EntityKey[de.finnrw.elba.server.ejb.test.Reservation#2], EntityKey[de.finnrw.elba.server.ejb.test.
Cruise#1]
2006-08-17 10:13:56,817 DEBUG [org.hibernate.loader.Loader] found row of collection: [de.finnrw.elba.server.ejb.test.Cruise.reservations#1]
2006-08-17 10:13:56,817 DEBUG [org.hibernate.jdbc.AbstractBatcher] about to close ResultSet (open ResultSets: 1, globally: 1)
2006-08-17 10:13:56,818 DEBUG [org.hibernate.jdbc.AbstractBatcher] about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
2006-08-17 10:13:56,818 DEBUG [org.hibernate.jdbc.ConnectionManager] aggressively releasing JDBC connection
2006-08-17 10:13:56,818 DEBUG [org.hibernate.jdbc.ConnectionManager] releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally:
0)]
2006-08-17 10:13:56,820 DEBUG [org.hibernate.engine.TwoPhaseLoad] resolving associations for [de.finnrw.elba.server.ejb.test.Reservation#1]
2006-08-17 10:13:56,820 DEBUG [org.hibernate.engine.TwoPhaseLoad] done materializing entity [de.finnrw.elba.server.ejb.test.Reservation#1]
2006-08-17 10:13:56,820 DEBUG [org.hibernate.engine.TwoPhaseLoad] resolving associations for [de.finnrw.elba.server.ejb.test.Cruise#1]
2006-08-17 10:13:56,820 DEBUG [org.hibernate.engine.TwoPhaseLoad] done materializing entity [de.finnrw.elba.server.ejb.test.Cruise#1]
2006-08-17 10:13:56,821 DEBUG [org.hibernate.engine.TwoPhaseLoad] resolving associations for [de.finnrw.elba.server.ejb.test.Reservation#2]
2006-08-17 10:13:56,821 DEBUG [org.hibernate.engine.TwoPhaseLoad] done materializing entity [de.finnrw.elba.server.ejb.test.Reservation#2]
2006-08-17 10:13:56,821 DEBUG [org.hibernate.engine.CollectionLoadContext] 1 collections were found in result set for role: de.finnrw.elba.server.ejb.test.Cruise.reservat
ions
2006-08-17 10:13:56,821 DEBUG [org.hibernate.engine.CollectionLoadContext] collection fully initialized: [de.finnrw.elba.server.ejb.test.Cruise.reservations#1]
2006-08-17 10:13:56,821 DEBUG [org.hibernate.engine.CollectionLoadContext] 1 collections initialized for role: de.finnrw.elba.server.ejb.test.Cruise.reservations
2006-08-17 10:13:56,821 DEBUG [org.hibernate.engine.StatefulPersistenceContext] initializing non-lazy collections
2006-08-17 10:13:56,821 DEBUG [org.hibernate.loader.Loader] done entity load
2006-08-17 10:13:56,822 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] executing identity-insert immediately
2006-08-17 10:13:56,822 DEBUG [org.hibernate.jdbc.AbstractBatcher] about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
2006-08-17 10:13:56,822 DEBUG [org.hibernate.jdbc.ConnectionManager] opening JDBC connection
2006-08-17 10:13:56,822 DEBUG [org.hibernate.SQL] insert into RESERVATION (DATE, AMOUNT, CRUISE_ID) values (?, ?, ?)
2006-08-17 10:13:56,823 DEBUG [org.hibernate.id.IdentifierGeneratorFactory] Natively generated identity: 3
2006-08-17 10:13:56,823 DEBUG [org.hibernate.jdbc.AbstractBatcher] about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
2006-08-17 10:13:56,823 DEBUG [org.hibernate.jdbc.ConnectionManager] aggressively releasing JDBC connection
2006-08-17 10:13:56,823 DEBUG [org.hibernate.jdbc.ConnectionManager] releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally:
0)]
2006-08-17 10:13:56,823 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] processing flush-time cascades
2006-08-17 10:13:56,823 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] dirty checking collections
2006-08-17 10:13:56,824 DEBUG [org.hibernate.engine.CollectionEntry] Collection dirty: [de.finnrw.elba.server.ejb.test.Cruise.reservations#1]
2006-08-17 10:13:56,827 DEBUG [org.hibernate.engine.Collections] Collection found: [de.finnrw.elba.server.ejb.test.Cruise.reservations#1], was: [de.finnrw.elba.server.ejb
.test.Cruise.reservations#1] (initialized)
2006-08-17 10:13:56,829 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] Flushed: 0 insertions, 0 updates, 0 deletions to 4 objects
2006-08-17 10:13:56,829 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] Flushed: 0 (re)creations, 1 updates, 0 removals to 1 collections
2006-08-17 10:13:56,829 DEBUG [org.hibernate.pretty.Printer] listing entities:
2006-08-17 10:13:56,829 DEBUG [org.hibernate.pretty.Printer] de.finnrw.elba.server.ejb.test.Reservation{amount=0, cruise=de.finnrw.elba.server.ejb.test.Cruise#1, date=11.
08.2006, id=3}
2006-08-17 10:13:56,830 DEBUG [org.hibernate.pretty.Printer] de.finnrw.elba.server.ejb.test.Cruise{reservations=[de.finnrw.elba.server.ejb.test.Reservation#1, de.finnrw.e
lba.server.ejb.test.Reservation#2, de.finnrw.elba.server.ejb.test.Reservation#3], shipId=355, name=Titanic, id=1}
2006-08-17 10:13:56,830 DEBUG [org.hibernate.pretty.Printer] de.finnrw.elba.server.ejb.test.Reservation{amount=6000, cruise=de.finnrw.elba.server.ejb.test.Cruise#1, date=
10.08.2006, id=2}
2006-08-17 10:13:56,830 DEBUG [org.hibernate.pretty.Printer] de.finnrw.elba.server.ejb.test.Reservation{amount=5000, cruise=de.finnrw.elba.server.ejb.test.Cruise#1, date=
09.08.2006, id=1}
2006-08-17 10:13:56,830 DEBUG [org.hibernate.jdbc.ConnectionManager] aggressively releasing JDBC connection
2006-08-17 10:13:56,830 DEBUG [org.hibernate.jdbc.JDBCContext] TransactionFactory reported no active transaction; Synchronization not registered
2006-08-17 10:13:56,830 DEBUG [org.jboss.ejb3.entity.ManagedEntityManagerFactory] ************** closing entity managersession **************
2006-08-17 10:13:56,830 DEBUG [org.hibernate.jdbc.JDBCContext] TransactionFactory reported no active transaction; Synchronization not registered
2006-08-17 10:13:56,830 INFO [STDOUT] modify 'Reservation' list : PKs of persistent objects 'Reservation' ...
2006-08-17 10:13:56,831 INFO [STDOUT] modify 'Reservation' list : PK of object 'Reservation' = '1' ...
2006-08-17 10:13:56,831 INFO [STDOUT] modify 'Reservation' list : PK of object 'Reservation' = '2' ...
2006-08-17 10:13:56,831 INFO [STDOUT] modify 'Reservation' list : PK of object 'Reservation' = '0' ...