Update:I'll be doing a Javapolis Quicky on ActiveHibernate. In the meanwhile one-to-many (has-many in ActiveRecord speak) has been added to the mapping DSL example.
Tuesday, October 30, 2007
ActiveHibernate update
Just added basic many-to-one support in the mapping DSL. I still hope to have a JRuby on Rails application running with ActiveHibernate before Javapolis.
Tuesday, September 25, 2007
To DDD or not to DDD
Imagine the application you're currently working on. Imagine your users were happy with a primitive text based UI in a console, and imagine persistence was not an issue because you have an obscene amount of RAM (a billion terrabyte) and your server never crashes (so no DBMS needed).
Would there be any complexity left to deal with in your software? If the answer is no, you're lucky (in a way). If the answer to this highly hypothetical question is still yes, then domain driven design (DDD) might be the thing for you.
Would there be any complexity left to deal with in your software? If the answer is no, you're lucky (in a way). If the answer to this highly hypothetical question is still yes, then domain driven design (DDD) might be the thing for you.
Subclasses with ActiveHibernate
Finally I resumed my work on ActiveHibernate. It now uses a XmlMarkup Builder and the visitor pattern to sort out the relationships between different persistent classes and to generate the mapping XML internally. This might sound like overkill, but even to get inheritance up and running it seemed like the only way to keep things maintainable. Anyway, the Ruby code
generates the mapping
class Payment
include Hibernate
hattr_accessor :amount,:double
...
end
class CreditCardPayment < Payment
join_with_table do
hattr_accessor :creditCardType,:string
...
end
end
class ChequePayment < Payment
hattr_accessor :chequeNumber,:string
..
end
generates the mapping
<class name="Payment" table="PAYMENT">
<id name="id" type="long" column="PAYMENT_ID">
<generator class="native"/>
</id>
<discriminator column="PAYMENT_TYPE" type="string"/>
<property name="amount" type="double"/>
...
<subclass name="CreditCardPayment" >
<join table="CREDIT_CARD_PAYMENT">
<key column="PAYMENT_ID"/>
<property name="creditCardType" type="string" />
...
</join>
</subclass>
<subclass name="ChequePayment" >
<property name="chequeNumber" type="string" />
...
</subclass>
</class>
The <join/> construct in the CreditCardPayment mapping allows to combine the table-per-class-hierarchy and the table-per-subclass mapping strategies in one inheritance hierarchy. In the Ruby mapping DSL it can be nicely expressed with a class method (table name and key are optional arguments) and a block. The fact that a Ruby class definition is just ordinary Ruby code (with self referring to a Class object) opens a whole new world to the simple Java developer that I am.
In Subversion soon.
Tuesday, September 11, 2007
Deep Cloning an Object Graph in .NET
The other day I was looking at the really nice NHibernate mapping examples by Davy Brion. His entity base class looks like this:
It is used like so:
The Order class derives from a template class that uses the Order class itself as parameter. I had never seen this before, and, for example, it gives all your entities a Clone() method that returns the proper type.
What's even more interesting is the way the Clone() method has been implemented by just serializing to a memory stream, immediately followed by a deserialization. It gives you a deep clone of your entity, together with all child entities it references. This technique is robust, simple, clean and generic (requiring no extra development effort).
I can imagine some people will object to this because of performance, but that only makes me think of all the crimes that are committed daily in the name of performance and (premature) optimization.
public abstract class Entity
{
private long _id = -1;
public virtual long Id
{
get { return _id; }
}
public virtual T Clone()
{
MemoryStream memoryStream = new MemoryStream();
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(memoryStream, this);
memoryStream.Position = 0;
return (T)binaryFormatter.Deserialize(memoryStream);
}
}
It is used like so:
public class Order : Entity<Order>
{
//...
}
The Order class derives from a template class that uses the Order class itself as parameter. I had never seen this before, and, for example, it gives all your entities a Clone() method that returns the proper type.
What's even more interesting is the way the Clone() method has been implemented by just serializing to a memory stream, immediately followed by a deserialization. It gives you a deep clone of your entity, together with all child entities it references. This technique is robust, simple, clean and generic (requiring no extra development effort).
I can imagine some people will object to this because of performance, but that only makes me think of all the crimes that are committed daily in the name of performance and (premature) optimization.
Monday, August 27, 2007
ActiveHibernate follow-up
Not much happened the last couple of weeks because it was our summer vacation (which summer?). I have cleaned up the existing code a bit, and now I'm working on a Ruby way for Hibernate inheritance mapping.
Wednesday, August 15, 2007
Towards a mapping DSL for AH
Last week Ola Bini sent me a patch that showed a Hibernate mapping written inside the Ruby class definition, instead of relying on hand-written XML files (the horror!), like so:
By including the Hibernate module (as opposed to inheriting from a framework base class), the Hibernate mapping is generated and configured automatically. Utility class methods (like "save" and"find") and accessor methods for the mapped properties are also added.
It's all in the file dsl_test.rb (see the link in the top right corner for the code repository). It is far from complete, but thanks to Ola I can start filling the gaps (like inheritance, relations, components, ...). Let me know what you think!
class Project
include Hibernate
with_table_name "PROJECTS" #optional
primary_key_accessor :id,:long,:PROJECT_ID
hattr_accessor :date,:timestamp,:START_DATE
#column name is optional
hattr_accessor :name,:string
hattr_accessor :complexity,:double
hattr_accessor :size,:long
hattr_accessor :on_time,:boolean
end
By including the Hibernate module (as opposed to inheriting from a framework base class), the Hibernate mapping is generated and configured automatically. Utility class methods (like "save" and"find") and accessor methods for the mapped properties are also added.
It's all in the file dsl_test.rb (see the link in the top right corner for the code repository). It is far from complete, but thanks to Ola I can start filling the gaps (like inheritance, relations, components, ...). Let me know what you think!
Monday, August 6, 2007
First ActiveHibernate code on Google Code
Because it's all talk until the code runs, I have finally imported my code into a Google Code project (http://code.google.com/p/activehibernate). There is no formal release yet, so you'll have to use a Subversion client to get it (or just browse the repository online). There's a readme file that explains how to get the tests running.
All feedback is more than welcome, as I'm new to (J)Ruby. I'm also very interested in ideas for a Ruby-like interface to Hibernate. The first thing that should be done is replacing the hbm.xml mapping files by a kind of annotations or a DSL (inspired by Rails or GORM, the OR/M in Grails).
All feedback is more than welcome, as I'm new to (J)Ruby. I'm also very interested in ideas for a Ruby-like interface to Hibernate. The first thing that should be done is replacing the hbm.xml mapping files by a kind of annotations or a DSL (inspired by Rails or GORM, the OR/M in Grails).
Subscribe to:
Posts (Atom)