Summary | Admin | Home Page | Forums | Tracker | Bugs | Support | Patches | RFE | Lists | Tasks | Docs | News | CVS | Files
For Version .7

Table of Contents


Introduction

hloader is a tool for persistent object instances, expressed in XML, into a database using Hibernate. It is a Hibernate loader, thus the name.

Uses

It can be used for:
More than anything, hloader extends an near zero cost of change to this data, thus supporting the Agile approach of evolving your database design along with you code.

 Alternatives

The usual alternative is SQL scripts which can be run using the Ant sql task.

Why hloader is a good idea

Supported Databases

hloader supports and has been tested with the following databases:
hloader can support any database that Hibernate can. Because it uses Hibernate to do the actual loading it should work with any database for which there is a Hibernate dialect.

Java

Java Requirements

Hloader supports JDK1.2, 1.3, 1.4 and 5.

Hloader does not work with JDK1.1.

Dependencies

Hloader requires the following libraries:

Note that hloader's typical use is as a tool at development time, so it's dependencies do not affect the runtime software's dependencies. Most of the depdendencies are also Hibernate dependencies, with the exception of jelly and jexl which will be additional.

Version of Hibernate

The .7 release and CVS trunk supports Hibernate 3.

The hloader .6 branch supports Hibernate 2 and 2.1. Hibernate 3 had a package name change from net.sf.hibernate to org.hibernate along with many internal changes that break Hibernate compatibility.

Installation

Place hloader.jar and required dependencies into your Ant classpath.

Logging

Hloader uses the Apache Commons Logging library. It acts as a thin bridge between logging statements in the code and logging infrastructure detected in the classpath. It will use in order of preference: log4j, JDK1.4 logging and then its own SimpleLog .  This enables ehcache to use logging infrastructures compatible with Java versions from JDK1.2 to JDK5. It does create a dependency on Apache Commons Logging, however many projects, including Hibernate, share the same dependency.

To see what is going on when hloader is running, increase the logging level for net.sf.hloader.

An hloader starter data file

Use the following as a template for creating your own hloader files.

Hloader data files are enclosed in Jelly scripts. See http://jakarta.apache.org/commons/jelly.

<?xml version="1.0"?>
<!DOCTYPE project [
        <!ENTITY bootstrap SYSTEM "bootstrap.xml">
        ]>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:x="jelly:xml" xmlns:h="jelly:net.sf.hloader.jelly.HloaderTagLibrary">
    <h:loadobjects configuration="/hibernate.cfg.xml">
        <hloader package="com.lggi.sp.common.spatial.core">
            <converters>
                <converter class='java.util.Date' name='net.sf.hloader.converter.DateConverter'/>
            </converters>
            <loader dialect='org.hibernate.dialect.MySQLDialect'
                nextIdentity='set insert_id = {0};'/>
            <loader dialect='org.hibernate.dialect.SqlServerDialect'
                identityGenerationDisableString='set identity_insert {0} on;'
                identityGenerationEnableString='set identity_insert {0} off;'/>
            <loader dialect='org.hibernate.dialect.Oracle9Dialect'
                resetNextIdentityGeneratedValueString='alter sequence = {0};'/>
            <loader dialect='org.hibernate.dialect.HSQLDialect'/>
            <j:new var="dateUtil" className="net.sf.hloader.util.DateUtil"/>
            <j:set var="now" value="${dateUtil.time}"/>
            <j:set var="today" value="${dateUtil.startOfDay}"/>
            <j:set var="DAY" value="86400000"/>
            <j:set var="yesterday" value="${dateUtil.addDays(-1)}"/>
            <j:set var="tomorrow" value="${dateUtil.addDays(1)}"/>

            <defaults>
                <!-- Add default values for objects here -->              
            </defaults>


            <objects>
                <!-- Add objects here-->
            </objects>

        </hloader>
    </h:loadobjects>
</j:jelly>

Tags

The xml data file is broken into two sections:

jelly

<j:jelly trim="false" xmlns:j="jelly:core" xmlns:x="jelly:xml" xmlns:h="jelly:net.sf.hloader.jelly.HloaderTagLibrary">
     <h:loadobjects configuration="/hibernate.cfg.xml">
           <!-- hloader element goes here -->
     </h:loadobjects
</j:jelly>

loadobjects

load objects is a Jelly tag which loads objects defined in the hloader element, using the Hibernate configuration specified.

configuration - the path to the Hibernate configuration file.

hloader

The hloader element has a defined DTD. It is:
<?xml version='1.0' encoding='utf-8'?>
<!ELEMENT hloader (converters|loaderdialects|defaults|objects)*>
  <!ATTLIST hloader package CDATA #REQUIRED>
<!ELEMENT converters (converter)*>
<!ELEMENT converter EMPTY>
<!ATTLIST converter
    name CDATA #REQUIRED
    class CDATA #REQUIRED>
<!ELEMENT loaderdialects (loader)*>
<!ELEMENT loader (#PCDATA)>
<!ATTLIST loader
    dialect CDATA #REQUIRED
    resetNextIdentity CDATA #IMPLIED
    setNextIdentityGeneratedValueString CDATA #IMPLIED>
<!ELEMENT defaults (#PCDATA)>
<!ELEMENT objects (#PCDATA)>

hloader has one attribute: the package name. This is a prefix that will be applied to defaults and objects elements to minimise typing. It is mandatory.

So, if you have two persistent objects called com.blah.project.Object1 and com.blah.project.dog.Object2 you could set the package name to com.blah.project. You could then declare your two objects
as Object1 and dog.Object2.

converters

A converter performs extra conversion over and above that provided by Hibernate.

<!ELEMENT converters (converter)*>
<!ELEMENT converter EMPTY>
<!ATTLIST converter
    name CDATA #REQUIRED
    class CDATA #REQUIRED>

<converter class='java.util.Date' name='net.sf.hloader.converter.DateConverter'/>
class - the fully qualified class name of the Class to convert
name - the name of the converter

Hloader has a Date and Timestamp converter to allow date calculations resulting in longs to be converted to Date or Timestamp objects.

loaderdialects

Hloader has been tested with MySQL, Oracle, MS SQLServer and HSQLDB.
 
The completed loader elements are shown for these databases below:

MySQL
<loader dialect='org.hibernate.dialect.MySQLDialect'
            nextIdentity='set insert_id = {0};'/>

MS SQL Server
<loader dialect='org.hibernate.dialect.SqlServerDialect'
            identityGenerationDisableString='set identity_insert {0} on;'
            identityGenerationEnableString='set identity_insert {0} off;'/>

Oracle
<loader dialect='org.hibernate.dialect.Oracle9Dialect'
            resetNextIdentityGeneratedValueString='alter sequence = {0};'/>

HSQLDB
<loader dialect='org.hibernate.dialect.HSQLDialect'/>

j:new and j:set

Because the hloader data is enclosed within a jelly script, you can define macros.

One possibility, and a useful one for setup data is to insert some commons dates. The example bootstrap xml
defines macros for "now", "today", "DAY" being the length of a day in ms, "yesterday" and "tomorrow".

<j:new var="dateUtil" className="net.sf.hloader.util.DateUtil"/>
<j:set var="now" value="${dateUtil.time}"/>
<j:set var="today" value="${dateUtil.startOfDay}"/>
<j:set var="DAY" value="86400000"/>
<j:set var="yesterday" value="${dateUtil.addDays(-1)}"/>
<j:set var="tomorrow" value="${dateUtil.addDays(1)}"/>

To use these in the defaults or objects elements, use the standard JSTL syntax of ${macroname}.

e.g. ${now} for now.

Ant properties are built-in. They do not require declaration using j:set. They can be accessed via ${antprops['property.name']}.

defaults

defaults contains persistent objects default field values. These are simply parsed character data as far as XML is concerned.

An example is:
<Region registrationAllowed="true" defaultTaxRate=".1" />
When an object such as Region is defined here, then the defined attributes will be applied to all objects created in
the objects element. In the example given:
The defaults section also lets you define whether objects have constant ids or not. If true, in the objects section
you can define the object id using the field name which is configure to be the Hibernate object id. 
To set constant ids for the object RoomFacility:

You need to use constantIds for objects that have associations, otherwise there is not way to set the association
between the right instances.

objects

objects contains persistent objects default field values. These are simply parsed character data as far as XML is concerned.

This is where the major work of hloader is done.

Define object instances using XML-like syntax, where the element name is the name of the persistent object class. The name of the
persistent object class is the "package" name defined in the hloader element, plus whatever is required to complete the fully qualified name of the
class. So, if you have two persistent objects called com.blah.project.Object1 and com.blah.project.dog.Object2 and the "package" name was set to "com.blah.project", you could then declare
 your two objects as Object1 and dog.Object2.

Fields of objects can be set using either attribute syntax:
         
<Country displayName="Australia" />


or nested element syntax:

<Country>
    <displayName>Australia</displayName>
</Country>

Associations

Associations between objects are set using nested elements with an 'id' attribute, eg
            
<Region ... >
       <country id="aus"/>
</Region>

Note that the nested element in the association is not the fully qualified class name, but the field name.
It is the name of the field where it has a standard JavaBeans accessor and mutator, and for collections the word following
the "add" in the add method. e.g. for addCountry, it would be Country.

This will use either a setter or adder method, eg setCountry(Country) or addCountry(Country).

If you have have a List or a Set of Countries, you will need to provide an addCountry(Country)
method in your Country domain object for hloader to use. This is not standard but is required for hloader
to work.

Object Ids

 There are several ways to set an object Id.

 When the object class uses assigned Ids, set the object Id as a regular property. Eg <Currency code="AUD"/>.

 When the object class uses native Ids (eg IDENTITY columns), and you want to use fixed Ids, then set 'constantIds'
 for the class to 'true'.  You can then set the object Id as per assigned Ids.

 When the object class uses native Ids and you want to use the generated Ids, there is no need to set the Id property.
 You can, however, give the object a temporary Id that can be used to reference the object in this file only.

  Note that the Id property of a class does not have to be called 'id'; The Hibernate mapping is used to figure out
  the name of the Id property.

An Example


Following is a full example of a data file. 
<?xml version="1.0"?>
<!DOCTYPE project [<!ENTITY bootstrap SYSTEM "bootstrap.xml">]>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:x="jelly:xml" xmlns:h="jelly:net.sf.hloader.jelly.HloaderTagLibrary">
<h:loadobjects configuration="/hibernate-noejb.cfg.xml">
<hloader package="project.domain">
<converters>
<converter class="project.valueobject.Money" name="project.valueobject.MoneyConverter"/>
<converter class='java.util.Date' name='net.sf.hloader.converter.DateConverter'/>
</converters>
<loaderdialects>
<loader dialect='net.sf.hibernate.dialect.MySQLDialect'
nextIdentity='set insert_id = {0};'/>
<loader dialect='project.dialect.SqlServerDialect'
identityGenerationDisableString='set identity_insert {0} on;'
identityGenerationEnableString='set identity_insert {0} off;'/>
<!-- individual table sequence reseting in hloader is not yet implemented -->
<loader dialect='project.dialect.OracleDialect'
resetNextIdentityGeneratedValueString='alter sequence = {0};'/>
</loaderdialects>
<j:new var="dateUtil" className="net.sf.hloader.util.DateUtil"/>
<j:set var="now" value="${dateUtil.time}"/>
<j:set var="today" value="${dateUtil.startOfDay}"/>
<j:set var="DAY" value="86400000"/>
<j:set var="yesterday" value="${dateUtil.addDays(-1)}"/>
<j:set var="tomorrow" value="${dateUtil.addDays(1)}"/>

<defaults>
<Country enabled="true" gmtOffset="10" registrationsEmailAddress="bootstrap-country@project.com"
bankLogoImageSrc="/image/bank_logo_National.gif" totalBookingFeeMoney="3.85" taxRate="0.1"
cancellationFeeMoney="25" registrationAllowed="true" defaultCommissionRate=".1" preferredIsoLanguageCode="en"
minimumDealPriceMoney="35" maximumDealPriceMoney="2000" commissionBeforeTax="false" projectBookingFeeTaxExempt="false"
 advancedSearchEnabled="true"/>
<!-- empty strings for fields like subRegion don't currently work the same in oracle as sqlserver or mysql. -->
<!-- star rating.rating is also an issue as oracle treats empty string as null. -->
<Region registrationAllowed="true" defaultTaxRate=".1" subRegion=""/>
<address.Locality postalCode="4000"/>
<Property active="true" starRating="3.5" comment="The property description goes here."
addr1="street" addr2="town" addr3="addr3" postCode="4000" starRatingCode="None"
carParking="Car parking info." thingsToDo="things to do." checkInTime="1400hrs" checkOutTime="1100hrs"
allowRoomDefaults="true" commissionRate="0.1"
secondaryRegistered="true" readTermsAndConditions="true" qualityAssured="true"
accountsEmailName="Accounts Manager" accountsEmailAddress="accountsmgr@supplier.com"
reservationsEmailName="Reservations Manager" reservationsEmailAddress="reservationsmgr@supplier.com"
salesName="Sales Dude" salesEmailAddress="sales@supplier.com">
</Property>
<RoomType displayName="Standard Room" normalRateMoney="100" roomTypeCode="STDROOM" bedTypePrompt="true"
details="Rates are per room for a maximum of 2 people using a king size bed, with seperate lounge room
 and private balcony with views of the river, city, southbank and western suburbs"
minimumNightStay="0" accomodationType="1 bedroom suite"/>
<Deal dealDate="${today}" maxRooms="5" roomsSold="0" inclusions="Inclusions"
advertisedRateMoney="100" nettRateMoney="82" nettRateTaxMoney="8" nettRateIncTaxMoney="90" commissionMoney="9"
commissionTaxMoney="1"
serverModifiedTimestamp="${today}" />
<PropertyFacility constantIds="true"/>
<PromotionType constantIds="true"/>
<RoomFacility constantIds="true"/>
<AccommodationType constantIds="true"/>
<PropertyChain constantIds="true"/>
<Promotion startTime="${today}"/>
<credit.CreditAccount name="creditAccount" active="true" email="admin@project.com" creationTimestamp="${now}"/>
<StaticText constantIds="true"/>
<ProjectStaffMember emailAddress="email@project.com" phoneNumber="07 3333 3333" photo="photo_temp.jpg"/>
<SupplierNewsletter sentDate="${today - (7 * DAY)}" body="this is the body of the newsletter"/>
<PropertyCancelPolicy constantIds="true" commentType="2"/>
</defaults>
<objects>
<Constant name="AccomDays" value="12"/>
<Constant name="HomePage_DefaultCountry" value="1"/>
<Constant name="HomePage_SplitRegionCountries" value="|1|"/>

<!-- Property Facilities -->
<PropertyFacility id="1" displayName="Room Service"/>
<PropertyFacility id="2" displayName="Gym / Fitness Room"/>
<PropertyFacility id="3" displayName="Restaurant"/>
<PropertyFacility id="5" displayName="Drycleaning / Laundry"/>
<PropertyFacility id="6" displayName="Lift"/>
<PropertyFacility id="7" displayName="Bar/Lounge"/>
<PropertyFacility id="8" displayName="24hr Front Desk"/>
<PropertyFacility id="9" displayName="Outdoor Swimming Pool" group="Swimming Pool"/>
<PropertyFacility id="10" displayName="Tour Desk"/>
<PropertyFacility id="11" displayName="Child Minding"/>
<PropertyFacility id="12" displayName="Tennis Court"/>
<PropertyFacility id="13" displayName="Disabled Facilities"/>
<PropertyFacility id="14" displayName="Spa"/>
<PropertyFacility id="15" displayName="Heated Swimming Pool" group="Swimming Pool"/>
<PropertyFacility id="16" displayName="Concierge"/>
<PropertyFacility id="17" displayName="Pets Allowed"/>
<PropertyFacility id="18" displayName="Currency Exchange Services"/>
<PropertyFacility id="19" displayName="Business Centre"/>
<PropertyFacility id="20" displayName="Business Centre with Internet Access"/>
<PropertyFacility id="21" displayName="Sauna"/>
<PropertyFacility id="22" displayName="Squash Court"/>
<PropertyFacility id="23" displayName="Nightclub"/>
<PropertyFacility id="24" displayName="Non-Smoking Floors"/>

<!-- Room Facilities -->
<RoomFacility id="1" displayName="Air Conditioning"/>
<RoomFacility id="2" displayName="Balcony"/>
<RoomFacility id="3" displayName="Bathrobes"/>
<RoomFacility id="4" displayName="Hairdryer"/>
<RoomFacility id="5" displayName="In house movies"/>
<RoomFacility id="6" displayName="Fax/Modem Telephone Line"/>
<RoomFacility id="7" displayName="Ironing equipment"/>
<RoomFacility id="8" displayName="Mini Bar"/>
<RoomFacility id="10" displayName="Self Catering (full kitchen)" group="Kitchen" nameWithinGroup="Full kitchen"/>
<RoomFacility id="11" displayName="In-room Spa bath"/>
<RoomFacility id="12" displayName="Tea/coffee making"/>
<RoomFacility id="13" displayName="Trouser Press"/>
<RoomFacility id="16" displayName="Dial-up Internet Access"/>
<RoomFacility id="17" displayName="Kitchenette (basic facilities)" group="Kitchen" nameWithinGroup="Basic facilities"/>
<RoomFacility id="18" displayName="Cable TV" group="Satellite/Cable TV" nameWithinGroup="Cable TV"/>
<RoomFacility id="19" displayName="Satellite TV" group="Satellite/Cable TV" nameWithinGroup="Satellite TV"/>
<RoomFacility id="20" displayName="Safe"/>
<RoomFacility id="21" displayName="Bath"/>
<RoomFacility id="22" displayName="CD Player"/>
<RoomFacility id="23" displayName="Broadband Internet Access"/>
<RoomFacility id="24" displayName="Opening Windows"/>

<!-- Some Currency Data -->
<Currency isoCurrencyCode="AUD" name="Australian Dollar" symbol="$" fractionalUnits="100"
minVoucherCents="2000" maxVoucherCents="200000"/>
<Currency isoCurrencyCode="USD" name="United States Dollar" symbol="$" fractionalUnits="100"
minVoucherCents="2000" maxVoucherCents="200000"/>
<Currency isoCurrencyCode="NZD" name="New Zealand Dollar" symbol="$" fractionalUnits="100"
minVoucherCents="2000" maxVoucherCents="200000"/>
<Currency isoCurrencyCode="EUR" name="Euro" symbol="&#x20ac;" fractionalUnits="100"
minVoucherCents="2000" maxVoucherCents="200000"/>
<Currency isoCurrencyCode="GBP" name="Pound Sterling" symbol="&#163;" fractionalUnits="100"
minVoucherCents="2000"
maxVoucherCents="200000"/>
<Currency isoCurrencyCode="JPY" name="Yen" symbol="&#165;" fractionalUnits="1"
minVoucherCents="200000" maxVoucherCents="20000000"/>
<!-- the following made-up currency is used to allow the SqlServerLockIntegrationTest to run and delete the currency
without getting constraint violations -->
<Currency isoCurrencyCode="MUD" name="Made-up Dollar" symbol="$" fractionalUnits="100"
minVoucherCents="2000" maxVoucherCents="200000"/>

<IsoCountry isoCode="AU" displayName="Australia"/>
<IsoCountry isoCode="NZ" displayName="New Zealand"/>
<IsoCountry isoCode="CA" displayName="Canada"/>
<IsoCountry isoCode="SG" displayName="Singapore"/>
<IsoCountry isoCode="HK" displayName="Hong Kong"/>
<IsoCountry isoCode="GB" displayName="United Kingdom"/>
<IsoCountry isoCode="US" displayName="United States"/>

<!-- Project offices -->
<ProjectOffice id="project-au" name="Brisbane"
tollFreePhoneNumber="1300 88 7979" phoneNumber="+61 7 3512 9999" faxNumber="+61 7 3512 9900"
physicalAddress="13 Railway Terrace\nMilton Qld 4064\nBrisbane - Australia"
postalAddress="">
<location id="AU"/>
</ProjectOffice>
<ProjectOffice id="project-ca" name="Ontario"
tollFreePhoneNumber="1 888 394 0616" phoneNumber="" faxNumber=""
physicalAddress="7B-920 Brant Street\nBurlington, Ontario\nL7R 4J1"
postalAddress="">
<location id="CA"/>
</ProjectOffice>
<ProjectOffice id="project-hk" name="Hong Kong"
tollFreePhoneNumber="800 901 922" phoneNumber="" faxNumber=""
physicalAddress=""
postalAddress="">
<location id="HK"/>
</ProjectOffice>
<ProjectOffice id="project-nz" name="New Zealand"
tollFreePhoneNumber="0800 441 092" phoneNumber="+64 9 836 7590" faxNumber="+64 9 836 7087"
physicalAddress=""
postalAddress="PO Box 69215\nGlendene\nAuckland">
<location id="NZ"/>
</ProjectOffice>

<!-- Job Positions -->
<JobPosition id="aus-job1" active="1" name="Product Development Manager"
description="Are you motivated by forming relationships that produce results? If so, this is the role for you.

The successful application will be responsible for a geographic region of hotels, liasing with staff."
essentialSkills="Relationship management experience
Ability to deliver exceptional customer service
A sound understanding of yield management principles"
preferredSkills="Hotel/Tourism experience"
howToApply="Describe two of your most satisfying customer service accomplishments.
What motivates you in the workplace?" creationTimestamp="${now}">
<ProjectOffice id="project-au"/>
</JobPosition>
<JobPosition id="aus-job2" active="0" name="Inactive Position"
description="Are you motivated by forming relationships that produce results? If so, this is the role for you.

The successful application will be responsible for a geographic region of hotels, liasing with staff."
essentialSkills="Relationship management experience
Ability to deliver exceptional customer service
A sound understanding of yield management principles"
preferredSkills="Hotel/Tourism experience"
howToApply="Describe two of your most satisfying customer service accomplishments.
What motivates you in the workplace?" creationTimestamp="${yesterday}">
<ProjectOffice id="project-au"/>
</JobPosition>
<JobPosition id="nz-job" active="1" name="New Zealand Position"
description="Are you motivated by forming relationships that produce results? If so, this is the role for you.

The successful application will be responsible for a geographic region of hotels, liasing with staff."
essentialSkills="Relationship management experience
Ability to deliver exceptional customer service
A sound understanding of yield management principles"
preferredSkills="Hotel/Tourism experience"
howToApply="Describe two of your most satisfying customer service accomplishments.
What motivates you in the workplace?" creationTimestamp="${tomorrow}">
<ProjectOffice id="project-nz"/>
</JobPosition>

<Country id="aus" displayName="Australia" isoCountryCode="AU" registrationsEmailAddress="bootstrap-country@project.com">
<currency id="AUD"/>
<projectOffice id="project-au"/>
</Country>

<!-- Set of advanced search facilities for Australia -->
<AdvancedSearchFacility id="aus" displayName="Tennis Court" displaySeqNo="10">
<country id="aus"/>
<propertyFacility id="12"/>
</AdvancedSearchFacility>

<address.StreetType id="street" name="Street" sortOrder="1">
<country id="aus"/>
</address.StreetType>
<address.StreetType id="avenue" name="Avenue" sortOrder="1">
<country id="aus"/>
</address.StreetType>
<address.StreetType id="road" name="Road" sortOrder="1">
<country id="aus"/>
</address.StreetType>

<address.AdministrativeArea id="qld" name="QLD">
<country id="aus"/>
</address.AdministrativeArea>
<address.AdministrativeArea id="nsw" name="NSW">
<country id="aus"/>
</address.AdministrativeArea>

<address.Locality id="brisbane" name="Brisbane City">
<administrativeArea id="qld"/>
</address.Locality>
<address.Locality id="westend" name="West End" postalCode="4101">
<administrativeArea id="qld"/>
</address.Locality>
<address.Locality id="sydney" name="Sydney City" postalCode="2000">
<administrativeArea id="nsw"/>
</address.Locality>

<!-- Credit cards -->
<payment.CreditCardType id="VISA" name="VISA" displayName="Visa"/>
<payment.CreditCardType id="MASTERCARD" name="MASTERCARD" displayName="Mastercard"/>
<payment.CreditCardType id="BANKCARD" name="BANKCARD" displayName="Bankcard"/>
<payment.CreditCardType id="AMEX" name="AMEX" displayName="American Express"/>
<payment.CreditCardType id="DINERS" name="DINERS" displayName="Diners Club"/>
<payment.CreditCardType id="DELTA" name="DELTA" displayName="Delta"/>
<payment.CreditCardType id="SWITCH" name="SWITCH" displayName="Switch"/>
</objects>
</hloader>
</h:loadobjects>
</j:jelly>
Notes:
  1. hloader, package attribute defines your toplevel domain package, ie. we are loading net.sf.hloader.domain.Country class
  2. loaderdialects, specifies the sql syntax used by different dialects if constantids are required.
  3. defaults, allows setup of defaults for any object, also allows for specification of which objects will specify their identity column.
In this example Country's id column is actually a natively generated database integer, yet we can use a nicer type to reference it in dependant object declarations.

Additional Requirements for Hibernate Persistent Classes to be hloadable

There are minimal changes to your Java classes to use hloader, mainly for the use of adding elements to collections. An Object instance needs to be declared prior to it be referenced by an enclosing class. You can see this in the above example, Country Australia is declared and used by City.
  1. Collections, any collections need to have an void addClassName(ClassName obj) on the parent class.
  2. components, must have a Id property with getter and setter, this is for hloader only, it doesn't have to be declared as a hibernate property or id.

Invoking hloader

Hloader is designed to be run from Ant. or programmatically.

From Ant

An example Ant target is shown below:


<!-- loadup the db - expected schema must already exist. -->
<target name="loaddb">
<taskdef name="hloader" classname="net.sf.hloader.tasks.JellyTask">
<classpath>
<path location="${tasks.classes.dir}"/>
<path location="${test.classes.dir}"/>
<path location="${build.classes.dir}"/>
<path refid="project.class.path"/>
</classpath>
</taskdef>

<!-- Load data -->
<hloader script="${test.classes.dir}/bootstrap.xml" escapeXml="false"/>
</target>


Programmatically


Hloader can also be executed programmatically.
ObjectLoader loadObjects = new ObjectLoader(inputstream, hibernateConfigFile);
loadObjects.execute();

For more information see the test suite, which is with the src code.

Developing hloader

If you wish to set up a development environment for hloader, checkout the code using CVS.

By default the build.properties point to MySQL, primarily because it is free and common. You will need a test database setup on your localhost as follows:

database: hloader
username: hloaderuser
password: hloaderpassword

Credits

hloader was an idea that sprung from the prolific mind of Adam Murdoch. Working with Adam on a project it is hard not to get left behind. Adam came up with the idea and first implementation in
a single afternoon for SQLServer.

To get what is a reasonable chunk of infrastructure code out of our project we decided to make it a project and open source it. Brett Dargan took on that task. Brett took an initial implementation to a project.

Greg Luck is mainly interested in making sure the word gets out and others make use of this project. He did the Hibernate 3 port, does code cleanups and documentation.


SourceForge.net