There is an initial implementation: equip2.persist.hibernate.j2se.PersistentDataspace.
It is currently quite limited:
The sample server is equip2.persist.hibernate.test.j2se.PersistentDataspace.
This will read hibernate configuration from the file hibernate.cfg.xml in the root
of the classpath. A standard sample is hibernate.cfg.xml.
This file includes details of the underlying Relational database to use
(via JDBC) and references to all of the individual object class mapping
files to be used: these must be provided for each class to be stored in
Hibernate (see for example MyDataType.hbm.xml
for equip2.net.test.MyDataType.
<!-- HSQLDB in-process database - simple/testing/development -->
<property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="connection.url">jdbc:hsqldb:file:hsql_test_db</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>
<property name="dialect">org.hibernate.dialect.HSQLDialect</property>
Note that the username & password are standard HSQLDB defaults for an in-process database.
The nice thing about this is that no separate install is required. However, HSQLDB may be less durable than mySQL in the presence of some failures. It is also unclear how well its performance scales to larger dataspaces.
The ant target hibernate_run will run a test application against the default persistent dataspace, initially HSQLDB as configured above.
To get unicode support with Hibernate and mySQL one known working
method is to set the database's default character set to utf8 before
creating the database and running Hibernate. For example, this may be
specified by the line:
[mysqld]
...
default-character-set=utf8
default-collation=utf8_bin
in the configuration file my.ini,
which may (depending on installation/version) be found in C:\Program Files\MySQL\MySQL Server 5.0.
Before using a mySQL-backed persistent dataspace the database must
have been set up as per the configuration in hibernate.cfg.xml,
for example on mySQL you might do:
create database equip2 character set utf8 collate utf8_bin;
grant all on equip2.* to equip2@localhost identified by 'equip2';
flush privileges;
which would correspond to the (commented out) configuration:
<!-- mysql - production -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql:///equip2</property>
<property name="connection.username">equip2</property>
<property name="connection.password">equip2</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
Once the configuration has been done and the database created the same ant test target can be used (hibernate_run).
The simple bean generator now has support for generating Hibernate mapping files as well as java beans and EQUIP2 helper classes; see Simple_Bean_Generator.html.
All classes to be used in the persistent dataspace must have their own hibernate mapping files, which must be listed in the hibernate.cfg.xml configuration file, e.g.:
<mapping resource="equip2/net/test/MyDataType.hbm.xml"/>
<mapping resource="equip2/persist/hibernate/test/j2se/HibernateTestObject.hbm.xml"/>
<mapping resource="equip2/persist/hibernate/test/j2se/HibernatePerfTestObject.hbm.xml"/>
EQUIP2 requires (currently on J2SE, and always on J2ME) a simple
helper class for each POJO/JavaBean class that will be used in a
dataspace. This helper class describes the structure of the object (its
fields/properties), provides reflection-like set/get access to those
fields, performs matching between values of that type and templates
values, and extracts the 'identity' value (if any) from an object of
that type.
Hibernate requires a description of the O/R mapping for each
POJO/JavaBean class, for example a corresponding .hbm.xml mapping file. This
identifies the class's properties to be managed by hibernate, any
non-default SQL types or properties (e.g. not null) and any database ID
(primary key).
There are some issues with the definition and use of equals() and
hashCode(). In particular, Hibernate requires them to be defined for
objects that are to be used in Sets, but also recommends that they
consider "only the properties that form the business key, a key that
would identify our instance in the real world (a natural
candidate key)". However, EQUIP2 current relies on object equals to
check whether managed objects have been changed - which should include
all properties of the object (other than any Hibernate
dataspace-allocated ID property).
There is an initial implementation of Sets, but there are some
performance issues with mapping queries on this to Hibernate.
EQUIP2 ISession.add is
directly equivalent to Hibernate save(Object).
In the first case the added object becomes managed by the EQUIP2
session; in the latter case the saved object becomes managed by the
Hibernate session.
Note however that the EQUIP session add operation is performed
locally in the session, and only executed as a change in the session
end operation.
In order to map EQUIP2 get to Hibernate load we would need to have configured the EQUIP2 identity as the Hibernate (application-defined) key, and know this.
Alternatively and more generally, a query will be required to give the
effects of get? The two cases are:
In the first case (no identity) it MIGHT be possible to do an
update() for a new object (or merge(), or retrieval of previously
retrieved managed object for a object already in the session).
Alternatively an exact query would be required. This would be more
restrictive than a normal match because NULL must also match exactly.
EQUIP2 ISession.remove
corresponds directly to Hibernate delete.
Note however that the argument to delete must be a hibernate-managed
object. EQUIP2 remote operations are queued for enactment in
sessionEnd; they must have been managed within that session.
Consequently the EQUIP2 session will have included a prior add, which
is then discarded internally, or a prior get or match which returned
the object. Note that with a remote session the object being offered
for deletion will be a (twice-removed) copy of the Hibernate-managed
object which presumably corresponded to the result of the get/match.
Will delete work anyway? Or can the copy become managed using merge()? (update() should fail because the previous managed value should be there) Or we could keep a cache of the returned objects and map back to the local managed object by hashCode/equals.
It appears that Hibernate update() (or lock()) will not work at all
if the java object does not hold the DB identity. So the old local
managed object will need to be retrieved again (currently by an exact
query) and then removed.
EQUIP2 ISession.match has two main issues to deal with in relating to Hibernate:
The mapping of queries looks best done to a Criteria query, with .eq Restrictions for non-null template values.
Currently element-type handling is limited to simple types.