:mod:`jynx.lib.hibernate` -- Hibernate Support ============================================== .. module:: lib.hibernate :synopsis: Defines Jython annotations and test runners for of use of JUnit 4. .. moduleauthor:: Kay Schluehr Getting started --------------- Hibernate Download ~~~~~~~~~~~~~~~~~~ Download the latest `Hibernate Core `_ package as well as Hibernate Annotations. Open ``jynx/lib/hibernate.config.py`` and set the root paths of your ``Hibernate`` and ``Hibernate Annotations`` packages i.e. the variables ``HIBERNATE_PATH`` and ``HIBERNATE_ANNO_PATH``. Apache Derby ~~~~~~~~~~~~ Download `Apache Derby `_. Apache Derby is an RDBMS implemented in Java which doesn't require a database server. It is used by Jynx for testing purposes. Otherwise there isn't Derby specific code aside from some configuration and it shall be easy to replace Derby with your favorite DB. Open ``jynx/lib/hibernate/tests.__init__.py`` and set the root paths of your ``Derby`` package i.e. ``DB_PATH``. Hibernate Config ~~~~~~~~~~~~~~~~ Open ``jynx/lib/hibernate/hibernate.cfg.xml`` and change the properties as you wish. By default a new ``hiberjynxdb`` database will be created at the current working directory. Working with JPA/Hibernate annotations -------------------------------------- Using the Entity annotation ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Using the ``Entity`` annotation from ``jynx.lib.hibernate`` triggers the translation process of a Jython class into a Java Entity which can be used with Hibernate Annotations. **Example** .. sourcecode:: jython @Entity class Flight(Serializable): flight_id = jproperty("int") @Id @signature("int _()") def getFlightId(self): return self.flight_id @signature("void _(int)") def setFlightId(self, flight_id): return self.flight_id = flight_id **Other translating annotations** The ``Entity`` annotation is not the only annotation which is translating. Other translating annotations are * Embeddable * MappedSuperclass Boilerplate reduction with the bean_property decorator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The above ``Flight`` bean description can be reduced to .. sourcecode:: jython @Entity class Flight(Serializable): @Id @bean_property(int) def flight_id(_):_ Using the :func:`bean_property ` the ``flight_id`` as well as the getters/setters accordingly will be generated. Hibernate extension annotations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Some of Hibernates annotations, most notably ``Table`` and ``Entity`` conflict with equally named JPA annotations. This is a problem because Jynx usually imports classes by name i.e. :: import org.hibernate.annotations.Table; instead of :: import org.hibernate.annotations.*; The ``jynx.lib.hibernate`` package provides an ``hn_anno`` object for disambiguation purposes. Accessing Hibernate annotations from ``hn_anno`` is safe regarding JPA annotation conflicts. So one can safely use :: .. sourcecode :: jython @Entity # JPA @hn_anno.Entity # Hibernate class Foo(Serializable): ... Working with sessions --------------------- The ``janx.lib.hibernate`` library defines two context managers for ``with-statement`` usage. They handle opneing+closing sessions and opening+committing/rolling back transactions. .. class:: hn_session( *classes ) Context manager used to open/close sessions. :param classes: zero or more classes added to the ``AnnotationConfiguration`` object of Hibernate Annotations. .. class:: hn_transact( session ) Context manager used to handle transactions. The transaction is rolled back if an unhandled exception is raised within the with-statement block of ``hn_transact``. Otherwise it will be committed. :param session: the session which starts the transaction. **Example** .. sourcecode :: jython @Entity class Foo(Serializable): @Id @bean_property(int) def id(_):_ with hn_session(Foo) as session: with hn_transact(session): foo = Foo() foo.id = 789 session.persist(foo) Frequent Errors --------------- Some well known Hibernate errors and how to respond in the `jynx.lib.hibernate` context. AnnotationException: Reference to an unknown entity ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Example :: org.hibernate.AnnotationException: @OneToOne or @ManyToOne on org.jynx.gen.Person.address.type references an unknown entity: org.jynx.gen.AddressType The type *AddressType* could not be found when the ``SessionFactory`` was built. This can be fixed easily by adding :: with hn_session(..., AddressType) as session: