Hi,

(I am cross-posting this on Clojure and Hibernate-users mailing list.)

DISCLAIMER: I am a Clojure newbie - please let me know if you find any
of my assumptions / statements to be incorrect.


Hibernate has an experimental support for working with maps rather
than POJOs using the following configuration property:

hibernate.default_entity_mode=dynamic-map

I have done few simple successful tests using the above-mentioned
technique, using Clojure/Hibernate/XML-hbm-files. The stack I tested
these with is below:

Windows XP 32-bit SP3
Sun JDK 1.6
Clojure 1.0
Hibernate 3.2
PostgreSQL 8.3
JDBC 3 driver


I am wondering if I can take this idea to a larger implementation
scale using Clojure. What I intend to achieve is described below in
detail. The intention of this post is to communicate the idea and
gather feedback - please provide your input, feedback, suggestions and
warnings.


- I am trying to visualize a dual layered easy-ORM for Clojure using a
subset of Hibernate. The first layer "Hibernate integration
primitives" will provide low level access to Hibernate functionaly
using Clojure and another layer "Easy ORM semantics" will build on the
top of the first layer and will provide Django / ActiveRecord like
ease of use.

- The domain model will be expressed using Clojure syntax (DSL). As a
pre-compile step, a utility function will process the domain model to
automatically generate Hibernate XML-mapping files. Those XML-mapping
files can be used to carry out hbm2ddl (optional) activities. The
domain model will also be rich enough to capture metadata for
subsequent Hibernate operations.

                    .-----> Auto-generate Hibernate XML as a
precompile step
                   /
                  /
    Clojure ORM Domain Model
                  \
                   \
                    *-----> Keep model's metadata in Clojure
                          (so that they can be applied in subsequent
operations)

- The captured domain model will retain information about entity-
identification, property names, associations etc. A fictitious sample
(only for example, not necessarily correct syntax) is given below:

    ; define model (HBM = Hibernate Mapping)
    ;
    ; extra (optional) attributes appear in the map
    ;
    (defmodel :blogentry                      ; assumed :entity-
name=:blogentry, :table=(upper-case :blogentry)

      (hbm-id :id :long {:column "AUTO_ID" :generator
"sequence" :sequence-name "blogentry_auto_id_seq"})   ;
assumed :name=:id, :type=:long, :column="AUTO_ID"

      (hbm-property :title       :string    {:width 100 }) ;
assumed :name=:title,       :type=:string,    :column=(upper-
case :title)

      (hbm-property :content     :string    {:width 3000}) ;
assumed :name=:content,     :type=:string,    :column=(upper-
case :content)

      (hbm-property :when-posted :timestamp              ) ;
assumed :name=:when-posted, :type=:timestamp, :column=(upper-case
(dash-to-underscore :when-posted))

      (hbm-property :is-deleted  :boolean                ) ;
assumed :name=:is-deleted,  :type=:boolean,   :column=(upper-case
(dash-to-underscore :is-deleted))

      (hbm-property :sample      :integer   {:column
"SAMPLE_CHAPTER" }) ;
assumed :name=:sample, :type=:integer, :column="SAMPLE_CHAPTER")

      ; associations
      (hbm-many-to-one     :blog {:column "BLOG_ID" :entity :blog-
entity})

      (hbm-set-one-to-many :usercomments {:key-column
"AUTO_ID", :entity :usercomments-entity} ))

    (defn create-blog-instance []

      (model-instance :blogentry

        { :title "Nandi Hills", :content "Fill here", :when-posted
(time-now), :is-deleted false } ))

    ; create instance and persist (HBO = Hibernate Operation)
    ;
    (let [blogentry (create-blog-instance)]

      (hbo-persist blogentry))

- There will be a Clojure DSL for persistence operations (that
ultimately translates into HQL or JPA QL). Some examples are below:

    (hbo-persist    blogentry-instance)

    (hbo-findby-id  blogentry 45)

    (:blog (hbo-findby-id blogentry
45))                               ; returns the blog entity from many-
to-one association

    (hbo-findby-any blogentry (:where [:eq :title "Amarnath Trip"]))

    (hbo-findby-any [blogentry :e usercomments :c] (:where [:eq
[:e :id] [:c :entry-id]]) ; Join

    (hbo-findby-any usercomments (:where [:not-in (:select [:id] :from
[:spammers])]))    ; Sub-select

    (hbo-updateall  blogentry :set [:title "New title" :is-deleted
false])

    (hbo-updateby-any  blogentry :set [:title "New title" :is-deleted
false] (:where [:gt :when-posted (parse-date "2009-06-30")]) )

    (hbo-deleteby-id blogentry 57)


- These are the simple design notes:

    ;- DSL Syntax for models should capture both Hibernate mapping and
model metadata
    ;
    ;- Remain close to Hibernate idioms, but do not inherit the XML-
wrinkles
    ;
    ;- Important HBM attributes are mandatory parameters in the domain
model
    ;
    ;- Rest of the (optional) attributes can appear as a map e.g.
{:column "CUSTOMER"}
    ;
    ;- Simplify in favour of succinctness (Sensible and auto-deduced
metadata defaults)
    ;
    ;- Overridable simplicity (Can override attributes by providing
maps, add children)
    ;
    ;- Not everything is covered - use hbm-any for direct Hibernate
API access (cook your own)
    ;
    ;- Use Clojure metadata support and (Cannot avoid) macros for
model definition
    ;
    ;- Use multimethods for XML auto-generation
    ;
    ;- Use macros and multimethods for persistence operations (render
as HQL / JPA QL)


Regards,
Shantanu

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to