Hallo Forengemeinde,
als Neuling hat man es immer schwer. Aber meine Hoffnung ist groß, dass ich hier eine gute Hilfe erhalte.
Ich nutze HSQLDB als Datenbank und Hibernate in Version 3.
Mein erstes Projekt:
Eine einfache Datenbank, die Bücher und Autoren verwalten soll.
Klasse Book beinhaltet unter anderem ein Set aus Autoren:
Set<Author>
Klasse Author beinhaltet unter anderem ein Set aus Büchern:
Set<Book>
Mit addAuthor(...), removeAuthor(...)
respektive
addBook(...) und removeBook(...)
greife ich auf die Sets zu.
Als Beispiel die addBook-Methode der Klasse Author:
Code:
public void addBook(Book book){
this.getBooks().add(book);
book.getAuthors().add(this);
}
Das habe ich aus der Hibernate-Einführung, ist also grundlegend.
Ich habe neben den Klassen Book und Author auch die beiden Klassen
BookManager und AuthorManager erstellt, um den Vorgang irgendwie in sich abzuschließen:
Code:
public static void addBookToAuthor(Long bookId, Long authorId){
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Author author = (Author) session.load(Author.class, authorId);
Book book = (Book) session.load(Book.class, bookId);
author.addBook(book);
session.getTransaction().commit();
}
Im Methodenrumpf besorge ich mir immer die aktuelle (sprich current) Session und führe die Aufgaben aus. Ist das so vernünftig im Sinne der Anforderung, atomisch zu bleiben?
Sollte man als Vorsichtsmaßnahme nur die ids der Objekte in die statische Methode geben und sie erst im Rumpf neu holen, so wie ich es mache?
Desweiteren habe ich ein Problem, wenn ich einen Autoren löschen möchte, dann soll bei jedem Buch die Verknüpfung entfernt werden. Macht Hibernate das automatisch, sobald ich den Autoren lösche oder muss ich die Bücher durchlaufen?
An dieser Stelle bin ich leider steckengeblieben.
Der Aufruf der deleteAuthor-Methode hier...
Code:
public static void deleteAuthor(Long authorId){
try {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Author author = (Author) session.load(Author.class, authorId);
session.delete(author);
session.getTransaction().commit();
}
catch(HibernateException e){
e.printStackTrace();
}
erzeugt ein Hibernate-Log:
Hibernate: delete from AUTHORS where AUTHOR_ID=?
und führt zur Exception:
Code:
org.hibernate.exception.ConstraintViolationException: could not delete: [prog.dbo.Author#1]
...
Caused by: java.sql.SQLException: Integrity constraint violation FKAC90951D7A7C806D table: AUTHOR_BOOK in statement [delete from AUTHORS where AUTHOR_ID=?]
Hier noch die beiden Mapping-Dokumente. Vielleicht habe ich da auch falsche Einstellungen getroffen. Bitte schaut mal:
Author.hbm.xml
Code:
<hibernate-mapping>
<class name="cs.prog.dbo.Author" table="AUTHORS" dynamic-update="true" dynamic-insert="true" select-before-update="false">
<id name="id" column="AUTHOR_ID">
<generator class="increment"/>
</id>
<property name="lastName"/>
<property name="firstName"/>
<property name="regDate" type="timestamp" column="REGISTRATION_DATE"/>
<set name="books" table="AUTHOR_BOOK" lazy="false" cascade="none" inverse="true">
<key column="AUTHOR_ID" />
<many-to-many column="BOOK_ID" class="prog.dbo.Book"/>
</set>
</class>
</hibernate-mapping>
Book.hbm.xml
Code:
<hibernate-mapping>
<class name="cs.prog.dbo.Book" table="BOOKS" dynamic-update="true" dynamic-insert="true" select-before-update="false">
<id name="id" column="BOOK_ID">
<generator class="increment"/>
</id>
<property name="title" not-null="true"/>
<property name="description"/>
<set name="authors" table="BOOK_AUTHOR" lazy="false">
<key column="BOOK_ID" />
<many-to-many column="AUTHOR_ID" class="prog.dbo.Author"/>
</set>
</class>
</hibernate-mapping>
Hoffentlich kommt Ihr mit den Infos klar. Falls nicht, reiche ich es schnellstmöglich nach. Ich danke schon mal im Voraus für die Mühe!