Archive for October, 2008

Hibernate Annotations for a One-To-Many Mapping Featuring a Many Side, Composite, Primary Key having a Composite, Foreign, Sub-Key

Tuesday, October 14th, 2008

Sure, that’s a honking title, but it is what’s needed to describe a Hibernate mapping that recently required some head scratching on my part to figure out. I’ve been off of Hibernate (as in off of the wagon) for a while now as I’ve been busy writing stored procedures. Now that I’ve fallen back on the wagon, and am working on a Spring/Hibernate project, I’ve started to recall what a joy/pain Hibernate can be.

This project has a legacy database so I had to map the database objects as is. The relationship is between a parent and child table (or master/detail set of tables), which I’m going to refer to as Parent and Child, respectively:

Parent and Child Tables

As the title of this post indicates Parent has a composite primary key. The interesting, and tricky to handle in Hibernate item is the primary key of the child table. This is also a composite key, and a sub-key of the Child primary key is a foreign key to Parent. The DDL for this relationship gives an exact picture of the relationship:

create table parent (
  id      integer,
  version integer,
  constraint parent_pk primary key (id, version)
);

create table child (
  id      integer,
  parent_id integer,
  parent_version integer,
  constraint child_pk
    primary key (id, parent_id, parent_version),
  constraint child_fk
    foreign key (parent_id, parent_version)
    references parent (id, version)
);

Two fields from Child (parent_id and parent_version ) point back to the owning Parent (id, version). There are a couple of aspects that make this harder to model from the Hibernate perspective. All of the keys involved are composite, so you have to use embedded objects to represent each key.

Secondly, there is no separation between the link to the parent and the existence of a child instance. Hibernate is most easy to deal with when these are two different items. That is why you see recommendations 1) against unidirectional OneToMany relationships with a foreign key on the owned entity, and 2) and that you use a join table in these cases. The join table lets you separate the existence of a child (a record in the child table) from the existence of the relationship to parent (a record in the join table). In this case, since the foreign key (the link) is part of the primary key (existence), these two concept are not separated and we need to just deal with it.

Against the above recommendation, one has to go with a OneToMany with no join table. I didn’t invent how to model this, the canonical posting for relationships with composite keys are here and here. However, those posting don’t deal with the combined primary and foreign key and when both keys are composite so there is some extra detail here. I’ve packaged the example up as an Eclipse project and the complete source code is available here.

Because the keys are composite, the Java object model has embedded objects that represent the primary key values, as shown in following class diagram:

Parent and Child Class Diagram

The main domain objects are named Parent and Child, which would also hold all of the additional attributes in a real application (I’m showing only key values here for clarity). The primary key objects are ParentPrimaryKey and ChildPrimaryKey. An important point to note here is the representation of the foreign key in ChildPrimaryKey. ChildPrimaryKey holds a reference to the owning Parent as an instance variable (named parentForeignKey).

Moving on to the annotations and the coding tasks that need to be applied to each of classes, we start with Parent:

package com.beavercreekconsulting.example;

import java.util.List;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "parent")
public class Parent {

  @Id
  ParentPrimaryKey primaryKey = new ParentPrimaryKey();

  @OneToMany(mappedBy = "primaryKey.parentForeignKey",
    fetch=FetchType.EAGER)
  private List children;

  public ParentPrimaryKey getPrimaryKey() {
    return primaryKey;
  }

  public void setPrimaryKey(ParentPrimaryKey primaryKey) {
    this.primaryKey = primaryKey;
  }

  public List getChildren() {
    return children;
  }

  public void setChildren(List children) {
    this.children = children;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result
      + ((children == null) ? 0 : children.hashCode());
    result = prime * result
      + ((primaryKey == null) ? 0 : primaryKey.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    final Parent other = (Parent) obj;
    if (children == null) {
        if (other.children != null) return false;
    } else if (!children.equals(other.children)) return false;
    if (primaryKey == null) {
      if (other.primaryKey != null) return false;
    } else if (!primaryKey.equals(other.primaryKey)) return false;
    return true;
  }
}

The Entity and Table annotations are straightforward JPA annotations. The Id annotation on the primaryKey instance variable indicates that an embedded object will be used for the primary key.

The @OneToMany annotation with the mappedBy element indicates a bidirectional relationship with the Many side as the owner.

Annotation of the ParentPrimaryKey is straightforward:

package com.beavercreekconsulting.example;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable;

@Embeddable
public class ParentPrimaryKey implements Serializable {

  private static final long serialVersionUID = -2912693560354598053L;

  @Column(name = "id")
  Integer id;

  @Column(name = "version")
  Integer version;

  public Integer getId() {
    return id;
  }

  public void setId(Integer id) {
    this.id = id;
  }

  public Integer getVersion() {
    return version;
  }

  public void setVersion(Integer version) {
    this.version = version;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.hashCode());
    result = prime * result + ((version == null) ? 0 : version.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    final ParentPrimaryKey other = (ParentPrimaryKey) obj;
    if (id == null) {
      if (other.id != null) return false;
    } else if (!id.equals(other.id)) return false;
    if (version == null) {
      if (other.version != null) return false;
    } else if (!version.equals(other.version)) return false;
    return true;
  }
}

The embeddable class needs to implement Serializable, so I added Eclipse generated serialVersionUID, hashCode() and equals().

The ChildPrimaryKey class is pretty similar to ParentPrimaryKey:

package com.beavercreekconsulting.example;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.ManyToOne;

@Embeddable
public class ChildPrimaryKey implements Serializable {

  private static final long serialVersionUID = -452758257162645576L;

  @Column(name="id")
  Integer id;

  @ManyToOne
  Parent parentForeignKey;

  public Integer getId() {
    return id;
  }

  public void setId(Integer id) {
    this.id = id;
  }

  public Parent getParentForeignKey() {
    return parentForeignKey;
  }

  public void setParentForeignKey(Parent parentForeignKey) {
    this.parentForeignKey = parentForeignKey;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.hashCode());
    result = prime * result
      + ((parentForeignKey == null) ? 0 : parentForeignKey.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    final ChildPrimaryKey other = (ChildPrimaryKey) obj;
    if (id == null) {
      if (other.id != null)
        return false;
    } else if (!id.equals(other.id))
      return false;
    if (parentForeignKey == null) {
      if (other.parentForeignKey != null)
        return false;
    } else if (!parentForeignKey.equals(other.parentForeignKey))
      return false;
    return true;
  }
}

The main annotations are @Column on the id field and @OneToMany on the parentForeignKey field. This class also needs to implement java.io.Serializable, so I added serialVersionUID, hashCode() and equals(). Eclipse pointed out that the hashCode() method might not work correctly due to it’s dependence on parentForeignKey unless Parent also implements hashCode(), so I added that to Parent.

The final class, Child has the most complicated annotations. The goal of the annotations is to point the persistence layer to the embedded primary key object for the purposes of object identification. Here is a quick check list of the annotation that need to be applied:

  1. The instance variable that points to the primary key object should be annotated with @EmbeddedId.
  2. Supply getters and setters for for primary key fields that are annotated with @Transient and delegate the setting and getting to the embedded primary key class.
  3. Use @AssociationOverrides to point the values of the embedded class. The name of the association to override has the form of <instance-var-name>.<embedded-class-property>.
  4. Use an @AssociationOverride for each instance variable involved. You are noting the fields of this class and how they will be mapped into the parent.
  5. For the composite foreign key, use @JoinColumn to point from the database field back to the mapped attribute in the parent object.

I do hope the above points help you to map your object in the unfortunate event that you have to deal with a similar situation. If nothing else, just copy-n-paste-n-edit from the following code:

package com.beavercreekconsulting.example;

import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.Table;
import javax.persistence.Transient;

@Entity
@Table(name = "child")
@AssociationOverrides( {
  @AssociationOverride(name = "primaryKey.id",
    joinColumns = @JoinColumn(name = "id")),
  @AssociationOverride(name = "primaryKey.parentForeignKey",
    joinColumns = {
      @JoinColumn(name = "parent_id",
        referencedColumnName = "id"),
      @JoinColumn(name = "parent_version",
        referencedColumnName = "version") }) })
public class Child {

  @EmbeddedId
  ChildPrimaryKey primaryKey = new ChildPrimaryKey();

  public ChildPrimaryKey getPrimaryKey() {
    return primaryKey;
  }

  public void setPrimaryKey(ChildPrimaryKey primaryKey) {
    this.primaryKey = primaryKey;
  }

  @Transient
  public Integer getId() {
    return getPrimaryKey().getId();
  }

  public void setId(Integer id) {
    getPrimaryKey().setId(id);
  }

  @Transient
  public Parent getParentForeignKey() {
    return getPrimaryKey().getParentForeignKey();
  }

  public void setParentForeignKey(Parent foreignKey) {
    getPrimaryKey().setParentForeignKey(foreignKey);
  }
}

The final section of code I have is an Example class which does a set of CRUD operations with this mapping. I’ve used Spring in the example since I’m starting to believe this is Hibernate’s natural environment:

package com.beavercreekconsulting.example;

import java.util.Arrays;
import java.util.List;
import java.util.Random;

import org.springframework.beans.factory.BeanFactory;

import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
* Main entry point for example
*/
public class Example {

  HibernateTemplate hibernateTemplate;

  public static void main(String[] args) {
    ClassPathResource resource = new ClassPathResource("beans.xml");
    BeanFactory bf = new XmlBeanFactory(resource);
    Example example = (Example) bf.getBean("example");
    example.go();
  }

  @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
  private void go() {
    create();
    read();
    update();
    delete();
    hibernateTemplate.flush();
  }

  private void update() {
    List parents = hibernateTemplate.find("from Parent");
    for (Parent p : parents) {
        Child c = new Child();
        c.setParentForeignKey(p);
        c.setId(new Random().nextInt());
        p.getChildren().add(c);
        hibernateTemplate.save(c);
    }
  }

  private void read() {
    List parents = hibernateTemplate.find("from Parent");
  }

  private void delete() {
  List parents = hibernateTemplate.find("from Parent");
  for (Parent p : parents) {
    for (Child c : p.getChildren()) {
      hibernateTemplate.delete(c);
    }
    hibernateTemplate.delete(p);
    }
  }

  void create() {
    ParentPrimaryKey ppk = new ParentPrimaryKey();
    ppk.setId(new Random().nextInt());
    ppk.setVersion(new Random().nextInt());
    Parent p = new Parent();
    p.setPrimaryKey(ppk);
    hibernateTemplate.save(p);

    Child c = new Child();
    p.setChildren(Arrays.asList(c));
    c.setParentForeignKey(p);
    c.setId(new Random().nextInt());
    hibernateTemplate.save(c);
  }

  public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
    this.hibernateTemplate = hibernateTemplate;
  }

  public HibernateTemplate getHibernateTemplate() {
    return hibernateTemplate;
  }
}

Jaxer 1.0 RC Support for REST and RPC

Thursday, October 9th, 2008

Jaxer 1.0 RC is out and getting ready to go. To me, the big news is that server side APIs such as REST and RPC protocols have been promoted to first class citizens.

Up to now, the Jaxer application server has been HTML template oriented. Jaxer is a Server Side JavaScript (SSJS) port of Mozilla, and of course, that’s a really cool thing. If you’re a JavaScript Ninja, you finally have an application server which speaks your native language.

However, up to 1.0 RC, the server side processing model has been page/template oriented. On the server side, you’ve had to provide a concrete HTML page on the server to trigger Jaxer processing. With the 1.0 RC, you can now map an URL to JavaScript files that provide the HTTP response. This feature makes is easier to provide REST or RPC interfaces on top of server side JavaScript code.

The configuration I’ve been using is Apache and the standalone Jaxer server. Jaxer comes bundled with Aptana’s Studio IDE which is the easiest configuration for getting started on Jaxer. However, you’ll have to come to terms with deploying Jaxer under Apache when you go to production (OK, sure, you can deploy to Aptana’s Cloud which deploys direct from Studio, but that’s another beta topic).

Recent releases (prior to 1.0) have allowed you to interrupt the normal template processing of page and substitute arbitrary content and content types to be returned to the client. In order to make this work, you’ve had to provide a file that Apache is configured to hand off to the Jaxer processor.

I’m working on an Jaxer application that responds to REST URLs. Here is the approach I was using for releases prior to 1.0. I wrote Apache mod_rewrite rule to hit a front controller, where the front controller is an HTML page that Jaxer processes. I added the following to my httpd.conf file:

RewriteEngine on
RewriteRule /world.* /world/index.html

My plan is that index.html will respond to REST URLs for POST, GET, PUT, and DELTE request such as :

http://<host>/world/<entity>/<id>

The one issue I ran into was that the Apache configuration that tells Apache to hand off a request to Jaxer for filtering needs a file extension and a content type. The above URL has no file extension. My solution was to place the font controller file in it’s own directory and set Jaxer filter handling to all content in the specified directory (in my httpd.conf file):

<Directory "c:/opt/xampp/htdocs/world">
JaxerFilter *
JaxerFilterContentType text/html
Order Deny,Allow
Deny from all
Allow from all
</Directory>

The good news is that the 1.0 RC allows direct specification of JavaScript files to handle REST type URLs. Tricks like the above rewrite rules won’t be need for REST. This is a big change as server side code stands alone, without a HTML page template. To me, this is the difference between a Servlet and a JSP.

With the 1.0 RC it appears that you can match URLs to execution of server side JavaScript files, which feels much more like a J2EE web.xml file which matches URLs to invocation of server side code (servlets).

I’m working up some examples of all this with 1.0 RC which aren’t quite baked yet. If you’re in a hurry to make REST work with 1.0, here are the files to look at from the standalone release:

jaxer\confs\jaxer-*.httpd.conf
jaxer\default_local_jaxer\conf\configApps.js
jaxer\framework\extensions\serviceDispatcher.js