Posts Tagged ‘java’

Use Hibernate’s Custom Loaders to fake an aggregation view

Your Problem
You have a data model with table that contains data you want to aggregate. For instance (returning to my venerable Pizza Shop example), let’s say you have a PRODUCT table that enumerates the items your pizza shops sells, and a LOCATION table that contains all of your retail locations:


We also have a table that contains the sum of all of the previous days’ sales, broken down by PRODUCT and LOCATION:

This is all well and good, but we’ve been asked to create an Executive Dashboard for the President of the pizza chain, and she would like to see daily sales by product. She is not interested in a breakdown by location.

We could tally it up client side…
What if we just loaded the entire table into the client, and iterated over the per-product results, and present that? Unfortunately, ORM libraries are pretty stupid in situations like these, and will generate all kinds of expensive reads to the database when you try to solve the problem this way. If you want to learn more about lazy loading, and why you shouldn’t iterate over a collection, check out my earlier post here.

We could just create a view in the Database…
We could just create a view, and aggregate the data there. Then we can easily create a Hibernate mapping to that view. The query for the view is simple:

CREATE VIEW sales_by_product_view AS
SELECT product_id, SUM(total_sales) AS total_sales
  FROM YESTERDAY_SALES
 GROUP BY product_id

However, we are working with a tyrannical DBA. She is not keen on proliferating views throughout our otherwise pristine schema every time the President has decided that the company needs a new widget for the executive dashboard application.

…or we could fake it with a custom loader
Instead, let’s create a Hibernate mapping that generates the same results as the view. First, let’s create a simple POJO to contain the results:

package us.mikedesjardins;
public class SalesByProduct {
  private Integer id;
  private Integer productId;
  private BigDecimal sales;
// accessors omitted
}

The corresponding mapping file would look like this. I re-used the product_id for the ID in this example. Note the loader element:

<hibernate-mapping package="us.mikedesjardins">
  <class name="SalesByProduct"
          dynamic-insert="false"
          dynamic-update="false"
          mutable="false">
    <id name="id" type="int" unsaved-value="null">
      <column name="__id" sql-type="int identity" not-null="true" unique="true" />
    </id>
    <property name="productId" type="int">
      <column name="__product_id" not-null="false" />
    </property>
    <property name="sales" type="java.math.BigDecimal">
      <column name="__total_sales" not-null="false" />
    </property>
    <loader query-ref="salesByProductQuery" />
  </class>
  <sql-query name="salesByProductQuery">
    <return class="SalesByProduct" />
    <![CDATA[
    select product_id as __id
         , product_id as __product_id
         , sum(total_sales) as __total_sales
      from YESTERDAY_SALES
     where product_id = :product_id
    group by product_id
   ]]>
  </sql-query>
</hibernate-mapping>

Note that you need to put a positional argument in the query, or Hibernate will get nasty about parsing it. Hope that helps!

Tags: , , ,
Posted in blog | 1 Comment »


Use Hibernate Validators to find Nasty DataTruncation exceptions

If you develop Hibernate applications against either Sybase or MS SQL Server databases, you may have had the pleasure of seeing this little gem:

09:13:22,155 WARN [] org.hibernate.util.JDBCExceptionReporter – SQL Error: 0, SQLState: 22001
09:13:22,155 ERROR [] org.hibernate.util.JDBCExceptionReporter – Data truncation
09:13:22,155 WARN [] org.hibernate.util.JDBCExceptionReporter – SQL Error: 8152, SQLState: 22001
09:13:22,155 ERROR [] org.hibernate.util.JDBCExceptionReporter – String or binary data would be truncated.
09:13:22,159 ERROR [] org.hibernate.event.def.AbstractFlushingEventListener – Could not synchronize database state with session
.
.
.
Caused by: java.sql.DataTruncation: Data truncation

The most maddening thing about these errors is that the database won’t tell you which column is being truncated. A likely scenario is that you’ve developed a Web or Swing UI that permits the user to enter a value for a String field which is ultimately persisted to a database column, and the UI is not restricting the maximum length of the user’s input to the size of that the column supports. The question is, which field is the offender?

Hibernate Validators to the Rescue!
Situations like this are why it’s a pretty good idea to validate your data at the domain layer of your project, and not rely on your database and presentation layer to do all of the validation. Fortunately, Hibernate makes this pretty painless with validator annotations. Just import the org.hibernate.validator.Length annotation, and add the @Length annotation in your entity class, e.g.:

@Column(name="description",length=20)
@Length(max=20)
private String description;

Note that putting the length attribute in the @Column annotation is not enough. That attribute is used for generating DDL, but will not cause any validation to take place.

Now that our new Annotation is in place, we get the slightly more useful stack-trace below:

org.hibernate.validator.InvalidStateException: validation failed for: us.mikedesjardins.data.persist.MyClass
at org.hibernate.validator.event.ValidateEventListener.validate(ValidateEventListener.java:148)
at org.hibernate.validator.event.ValidateEventListener.onPreInsert(ValidateEventListener.java:172)
at org.hibernate.action.EntityIdentityInsertAction.preInsert(EntityIdentityInsertAction.java:119)
.
.
.

Of course, you should catch these exceptions and do something less hostile with them. For now, we’ll just log the details and re-throw so you can get the general gist of what you can do. Here’s a generic insert method in a DAO base class:

public void insert(T valueObject, Class... clazz) {
 try {
   Session s = getSession();
   s.save(valueObject);
   s.flush();
   s.refresh(valueObject);
 } catch (InvalidStateException v) {
   setToRollback();
   log.error("insert(), failed validation " + valueObject.toString(), v);
   InvalidValue[] invalid = v.getInvalidValues();
   for (int i=0; i<invalid.length; ++i) {
     InvalidValue bad = invalid[i];
     log.error("insert(), " + bad.getPropertyPath()
     + ":" + bad.getPropertyName()
     + ":" + bad.getMessage());
   }
   throw v;
 }
}

As you can see, the InvalidStateException contains an array of InvalidValue objects which describe the nature of the validation error. You can either log this information, or even present it to the user.

Hope that helps! Do you use Hibernate’s validator annotations for something nifty? Let us know in the comments!

Tags: , ,
Posted in blog | Comments Off


The Hibernate Song

(to the tune of The Spiderman Theme Song from the original cartoon series)

Hibernate, Hibernate
O/R Mapping sure is great
Gavin King, and H-Q-L
Make my life a living hell
Look out! Here comes Hibernate!

Mapping Files in Hibernate
Wish my team would annotate
Are its queries optimized?
Who knows – it’s always a surprise
Hey there, there goes Hibernate!

Don’t fetch data now
Lazy load, ‘cuz you might guess
I don’t need it now
Hibernate, you do know best!

Hibernate, Hibernate
Friendly neighborhood Hibernate
Grab the jars, and climb aboard
OO models are your reward
To it…
Relational DBs are old-school
When you need a complex tool
You need the Hibernate!

Tags: , , ,
Posted in blog | 1 Comment »


Pizza Shop III : JPA Event Listeners

This comment was recently posted to one of my blog entries a while back:

So, let’s say your data model has some tables with a columns that indicate the last person who touched a record, like Madhan’s example above. In most applications, the end-users of the database client share a common login to the database, and have individual logins which are specific to the application’s domain (i.e., you don’t have a database login mapped to each end user; maintaining this scheme would be a nightmare). For that reason, triggers can’t be used as a solution, because database triggers don’t know anything about which application end-user is responsible for making a data change.

The last thing you want to do is litter your codebase with snippets of code that set the username on your persisted objects manually; not only is it unnecessary duplication, but you’ll probably also end up missing cases where you should be setting the username.

EventListeners to the Rescue
Fortunately, JPA supports the notion of “EventListeners.” An event listener intercepts many of the API calls that modify a persisted object’s lifecycle, and thus may be used to inject business logic that needs to be duplicated over many different objects. AOP aficionados might refer to this as a cross-cutting “aspect” of the domain layer.

Return to the Pizza Shop
Readers of my blog (all three of them, including me) might recall my venerable Pizza Shop example. Here are the earlier Pizza Shop posts if you’d like to catch up: Part 1 and Part 2. I’m going to drag the Pizza Shop out again to demonstrate how to create an “audited” table, which shows the last user who modified a record. As always, the source is available here, and it’s been tested against MySQL, Postgres, and MS SQL Server, with Hibernate, OpenJPA, and TopLink.

This takes just five easy steps… four, really, ‘cuz the fourth step creates a mock object for testing, so it doesn’t really count!

Step One – New schema
Add a nullable column named username to the Order table… something like this should work if you have existing pizzashop schema for some reason:

ALTER TABLE ORDER ADD username VARCHAR(10)

Step Two – Create an Interface and Implement It
This step isn’t strictly necessary, but it’s probably safe to assume that we’ll want to add this functionality to other tables someday. The interface just adds accessor methods for the username:

public interface AuditedObject {
  public String getUsername();
  public void setUsername(String username);
}

Then, make the Order table implement AuditedObject. Add a member variable with a mapping to the username column to the Order table, and corresponding accessor methods:

public class Order implements IdObject, AuditedObject {
.
.
  @Basic @Column(name="username")
  private String username;
.
.
  public String getUsername() {
      return username;
  }
  public void setUsername(String username) {
      this.username = username;
  }
.
.
}

Step Three – Add an EntityListener Annotation
This is the secret sauce. In the JPA Framework, EventListeners allow you to fire some trigger code when a lifecycle event occurs on a persisted object. You do this by associating your persisted class with an EventListener class. We’ll implement our EventListener class after we’ve added the following annotations:

@Entity @Table(name="PIZZA_ORDER")
@EntityListeners(AuditedEntityListener.class)
public class Order implements IdObject, AuditedObject {
.
.

Step Four – Write a Mock Object for the Username for Testing
In the real world, you’d probably stuff the username into the servlet context object. For our simple tests, we’ll need to mock up an object to maintain a username for the duration of our tests. It can be something stupidly simple, like this:

public class MockContext {
  private static String username;
 
  public static String getUsername() {
      return username;
  }
  public static void setUsername(String username) {
      MockContext.username = username;
  }
}

We’ll set the username at the start of our tests, and read the username from our MockContext from the EventListener.

Step Five – Write the EntityListener class
JPA allows you to inercept method calls using seven annotations:

  • @PrePersist and @PostPersist are called before and after an object is persisted.
  • @PreUpdate and @PostUpdate are called before and after synchronization with the database. @PreRemove and @PostRemove are called before and after an object is removed from the persistent state.
  • @PostLoad is invoked immediately after an object is loaded from the database.

In our case, we’re going to populate the username instance variable when the object is persisted, so we will want to create an EntityListener class with the @PrePersist annotation. The method’s signature takes an Object parameter which is the object getting updated, and returns void. The class will look something like this:

public class AuditedEntityListener {
  @PrePersist
  public void updateUser(Object o) {
      if (o instanceof AuditedObject) {
        String username = MockContext.getUsername();
        ((AuditedObject)o).setUsername(username);
      }
  }
}

Voila! When you run the tests, the username fields are populated and persisted!

Audit M&M’s Photo Courtesy Joe Hall.

Tags: , , ,
Posted in blog | 2 Comments »


Using JavaMail to read and extract attachments

Recently I had to create a JavaMail-based e-mail client that polled an IMAP server for incoming e-mail messages. The client needed to read each message, find any attachments, and save those attachments to a directory on the application server. I had never had a need to do this with the JavaMail API before, so I did the first thing that many developers do when they’re venturing into unknown territory, and Google’d for an example. I found lots of examples of sending attachments, but not many of receiving them. The few examples that I did find of receiving mail with the JavaMail API were too simple. So I had to figure out how to do it by (gasp) reading the documentation. Fortunately, it wasn’t very difficult, but I thought I’d share it for the next programmer that turns to Google for a solution.

In my application, I used the Quartz library to periodically call a method named receive, which does the grunt work of pulling stuff off the server. This code is similar to other examples you might find out there Google’ing, and it’s pretty mundane stuff. The MailReceiveException is a catch-all Exception class that I wrote:

public Message[] receive(String server, String user,
                         String password, String directory)
                 throws MailReceiveException {
  Message[] msgs;
  Store store = null;
  Folder folder = null;
  try {
    store = session.getStore("imap");
    store.connect(server, user, password);
    folder = store.getDefaultFolder();
    if (folder == null) {
      throw new MailReceiveException("No default folder");
    }
    folder = folder.getFolder("INBOX");
    if (folder == null) {
      throw new MailReceiveException("No IMAP INBOX");
    }
    folder.open(Folder.READ_WRITE);
    msgs = folder.getMessages();
    for (int i=0; i<msgs.length; ++i) {
      Message msg = msgs[i];
      // don't fetch messages that we've already processed
      if (!msg.isSet(Flags.Flag.SEEN)) {
        String from = "unknown";
        if (msg.getReplyTo().length >= 1) {
          from = msg.getReplyTo()[0].toString();
        } else if (msg.getFrom().length >= 1) {
          from = msg.getFrom()[0].toString();
        }
        String subject = msg.getSubject();
        String filename = directory + "/" + from + ": " + subject;
        // This is where the real work will get done.
        this.saveParts(msg.getContent(), filename);
        msg.setFlag(Flags.Flag.SEEN,true);
      } else {
        // Delete anything that is more than sixty days old.
        Date receivedOn = msg.getReceivedDate();
        GregorianCalendar cal = new GregorianCalendar();
        cal.add(GregorianCalendar.DATE,-60);
        if (receivedOn.before(cal.getTime())) {
          msg.setFlag(Flags.Flag.DELETED, true);
        }
      }
    }
 
    // Rats' nest of catch blocks omitted... make sure you close
    // the folder and the mail store in a finally block, as well
    // as expunge any messages that have been marked for deletion.
 
  }
  return msgs;
}

There’s one small detail that I had to learn the hard way, and that is that the “Parts” within Multipart MIME messages can themselves contain other Parts. So you have a nifty opportunity to use some of that fancy recursion stuff that you learned about in your “Intro to Programming” course!

public void saveParts(Object content,
                       String filename)
             throws MailReceiveException {
  OutputStream out = null;
  InputStream in = null;
  try {
    if (content instanceof Multipart) {
      Multipart multi = ((Multipart)content);
      int parts = multi.getCount();
      for (int j=0; j<parts; ++j) {
        MimeBodyPart part = (MimeBodyPart)multi.getBodyPart(j);
        if (part.getContent() instanceof Multipart) {
          // part-within-a-part, do some recursion...
          this.saveParts(part.getContent(), filename);
        } else {
          String type = part.getContentType();
          String extension = "";
          if (part.isMimeType("text/html")) {
            extension = "html";
          } else {
            if (part.isMimeType("text/plain")) {
              extension = "txt";
            } else {
              // Try to make a reasonable guess about the
              // extension from the MIME type.
              int end = type.indexOf(';');
              if (end < 0) {
                end = type.length();
              }
              extension = type.substring(type.indexOf('/')+1,end);
            }
            filename = filename + "." + extension;
            out = new FileOutputStream(new File(filename));
            in = part.getInputStream();
            int k;
            while ((k = in.read()) != -1) {
              out.write(k);
            }
          }
        }
      }
    }
  } catch (MessagingException e1) {
    log.error("Messaging Exception", e1);
    throw new MailReceiveException("Error fetching e-mail");
  } catch (IOException e2) {
    log.error("Caught IOException reading e-mail.", e2);
    throw new MailReceiveException("Error fetching e-mail");
  } finally {
    if (in != null) {
      try {
        in.close();
      } catch (IOException e6) {
        log.error("Unable to close input stream");
      }
    }
    if (out != null) {
      try {
        out.flush();
        out.close();
      } catch (IOException e7) {
        log.error("Unable to close output stream.");
      }
    }
  }
}

All of this work was done using JavaMail 1.3. I believe newer versions of the API have a savePart method, so you don’t need to write out the parts to a FileOutputStream byte-by-byte as I have above.

Tags: ,
Posted in blog | Comments Off


Pizza shop 2: Totaling the JPA Order, use P6Spy to prevent stupidity

I’m digging up the original Pizza Shop project to illustrate another Hibernate gotcha (it’s probably applicable to other ORM libraries as well… admittedly, I haven’t tested it). If you didn’t read the original Pizza Shop post, you can find it here. To review, here is an ERD for the system:
Today I’d like to show how not to total up the cost of the customer order. First, we are going to add P6Spy to the project. P6Spy is an excellent “JDBC wrapper” tool that sits between your application code and your actual JDBC driver. It intercepts your application’s JDBC requests and logs the results. It’s an invaluable tool for optimizing the voodoo out of an ORM tool, and the great thing is that it’s simple to setup:

1.) Change your application’s JDBC driver from whatever it currently is (e.g., org.postgresql.Driver), to the P6Spy JDBC driver, com.p6spy.engine.spy.P6SpyDriver.
2.) Modify the spy.properties file by editing the line that starts with “realdriver=”, changing the value to your actual JDBC driver.
3.) Put spy.properties on your classpath.

That’s it! Now that we have that out of the way, let’s see just how badly we can screw up a simple method in our Model class. The method we are going to add will total up the price of an order. If you look at the ERD above, you can infer that the total cost of an order is the sum of the base price for each pizza, depending on its size, plus the price of each pizza’s individual toppings.

So for our example order, let’s say we have the following:
1 Small Pizza with Pepperoni and Mushroom
1 Medium Pizza with Sausage and Onions
1 Large Pizza with Extra Cheese

You’ll recall that we created a Model class which provides a method for retrieving a List of Pizza objects that are associated with an order ID. The temptation is to create a method which looks something like this:

public BigDecimal getOrderPriceWrong(Integer orderId) {
  BigDecimal result = new BigDecimal(0.0);
  Order order = this.getOrder(orderId);
  for (Pizza pizza : order.getPizzas()) {
    result.add(pizza.getSize().getBasePrice());
    for (Topping topping : pizza.getToppings()) {
      result.add(topping.getPrice());
    }
  }
  return result;
}

Because Hibernate does lazy-fetching, it’s not going to attempt to calculate the total cost with as few queries as possible. Instead, Hibernate’s general philosophy is to defer any queries until it knows that it absolutely needs to do them, substituting empty proxy objects for populated ones until required. Usually this is an optimization, but in this case, Hibernate will do the following queries:

1.) Query to obtain an order object.
2.) One Query for each Pizza, joined to the Size, to obtain the base price.
3.) One Query per Topping, to obtain the topping price.

In all, we get nine individual SQL queries to compute the total price of our single fictional order. The proof is in the P6Spy’s output, spy.log, truncated below:

select order0_.pizza_order_id as pizza1_2_, order0_.version ...
select pizzas0_.pizza_order_id as pizza4_2_, pizzas0_.pizza_id ...
select pizzas0_.pizza_order_id as pizza4_2_, pizzas0_.pizza_id ...
select pizzas0_.pizza_order_id as pizza4_2_, pizzas0_.pizza_id ...
select toppings0_.pizza_id as pizza1_1_, toppings0_.topping_id ...
select toppings0_.pizza_id as pizza1_1_, toppings0_.topping_id ...
select toppings0_.pizza_id as pizza1_1_, toppings0_.topping_id ...
select toppings0_.pizza_id as pizza1_1_, toppings0_.topping_id ...
select toppings0_.pizza_id as pizza1_1_, toppings0_.topping_id ...

If your application is totaling up the price of Pizza orders all day, this can really add up! An alternative approach is to use two named queries to compute the total base price, and total topping price, for an order. For example, we might add the following annotation to the Pizza class:

@NamedQueries(
{
@NamedQuery(
 name="basePrice",
 query="select SUM(p.size.basePrice) " +
       "  from Pizza p " +
       " where p.order.id = :orderId"),
@NamedQuery(
 name="toppingPrice",
 query="select SUM(topping.price) " +
       "  from Pizza p join p.toppings as topping " +
       " where p.order.id = :orderId")
})

Then, you could add the following methods to the OrderDao:

public BigDecimal nullGuard(Query query) {
  BigDecimal result = (BigDecimal)query.getSingleResult();
  return (result == null ? new BigDecimal(0) : result);
}
 
public BigDecimal getOrderPrice(Integer orderId) {
  Query query1 = getEntityManager().createNamedQuery("basePrice");
  query1.setParameter("orderId",orderId);
  Query query2 = getEntityManager().createNamedQuery("toppingPrice");
  query2.setParameter("orderId", orderId);
  return nullGuard(query1).add(nullGuard(query2));
}

…and call into the DAO from the Model class, thusly:

public BigDecimal getOrderPriceRight(Integer orderId) {
  return this.orderDao.getOrderPrice(orderId);
}

When we run the P6Spy test now, we see a meager two queries where we used to have nine:

select SUM(size1_.pizza_size_base_price) as col_0_0_ from PIZZA ...
select SUM(topping2_.topping_price) as col_0_0_ from PIZZA ...

It pays to periodically use a tool like P6Spy on your application, to look for easy wins like this one!

I’ve included a complete working eclipse project that demonstrates this… it’s actually a tweaked version of the earlier Pizza Shop project. You can get it here.

Tags: , , , ,
Posted in blog | 5 Comments »


Enumerated Types with JPA, and your Sock Drawer

One feature of JPA that didn’t exist in plain-vanilla Hibernate is support for Enumerated types. I haven’t seen a lot of examples of this in practice or on the internet, so in this post I’ll show one example of how to use JDK 5 enumerations with JPA.

For our example, we are going to create an inventory system for our sock drawer. It is comprised of only two tables. The first table, called SOCK, contains one row per sock in our drawer. The columns of the table are:

  • sock_id – an auto-incrementing identity column.
  • sock_description – a varchar column for a free-form text description of the sock.
  • sock_pattern_id – a reference to a row in the SOCK_PATTERN table.

As you may have guessed, the SOCK_PATTERN table looks like this:

  • sock_pattern_id – an integer primary key. It’s not auto-incrementing, because we will want to have control over the contents of the field.
  • sock_pattern_description – a varchar column for a free-form text description of the pattern.

We need to “prime” our SOCK_PATTERN table with the valid patterns and create a foreign key relationship between the two tables:

INSERT INTO SOCK_PATTERN (sock_pattern_id,sock_pattern_description) VALUES (0,'SOLID');
INSERT INTO SOCK_PATTERN (sock_pattern_id,sock_pattern_description) VALUES (1,'STRIPES');
INSERT INTO SOCK_PATTERN (sock_pattern_id,sock_pattern_description) VALUES (2,'POLKA_DOT');
INSERT INTO SOCK_PATTERN (sock_pattern_id,sock_pattern_description) VALUES (3,'ARGYLE');

Note that we populated sock_pattern_id starting with zero; this is important because the Enumeration below is zero-indexed.

Next, let’s create the classes:

public enum SockPattern {
 SOLID, STRIPES, POLKA_DOT, ARGYLE
}
 
@Entity @Table(name="SOCK")
public class Sock {
 @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
 @Column(name="sock_id")
 private Integer id;
 
 @Column(name="sock_description")
 private String description;
 
 @Enumerated @Column(name="sock_pattern_id")
 private SockPattern pattern;
 
 public Integer getId() { return id; }
 public void setId(Integer id) { this.id = id; }
 
 public String getDescription() { return description; }
 public void setDescription(String description) { this.description = description; }
 
 public SockPattern getPattern() { return pattern; }
 public void setPattern(SockPattern pattern) { this.pattern = pattern; }
}

Now, to use our wonderful contraption, you’d do something like the following:

public class Demo {
 private static EntityManagerFactory emf;
 static {
     Demo.emf = Persistence.createEntityManagerFactory("sockdrawer");
 }
 
 @Test
 public void socksOne() {
     Sock sock = new Sock();
     sock.setDescription("My favorite sock.");
     sock.setPattern(SockPattern.ARGYLE);
     EntityManager em = Demo.emf.createEntityManager();
     em.getTransaction().begin();
     em.persist(sock);
     em.getTransaction().commit();
     em.close();
 }
}

There are some obvious pitfalls to this approach. The object/relational mapping is very brittle; for this code to work, the IDs in the database always need to match the values that the ORM tool gets from the enumeration. Changing these values at a later date could cause some surprising results, and you can’t insert new rows without updating the Enumeration and recompiling. It does obviate the need to map the SOCK_PATTERN table, and you won’t need to worry about the details of cascading the persistent state of related Sock and SockPattern objects.

It’s just a new tool in the JPA toolbox.

(The code in this blog post was tested w/ Postgres and Toplink)

Tags: , , ,
Posted in blog | 1 Comment »


A Delicious and Simple JPA Mapping tutorial: The Pizza Shop

So, another JPA tutorial. What makes this one different? Well, for one thing, this one comes with a working, downloadable project that works with Eclipse, NetBeans, and IntelliJ IDEA 7. It’s packaged with Hibernate, Toplink, and OpenJPA. And it’s been tested with MySQL, PostgreSQL, MS SQL Server, and Sybase. In other words, it works with 36 different IDE/JPA Provider/Database combinations!

Another thing that makes this tutorial different is the subject matter: Pizza! Who doesn’t love pizza? Except lactose intolerant people. And people who can’t eat gluten. But other than them, who doesn’t love pizza? So we’re going to create a simple database model for a pizza shop’s point-of-sale system.

The Schema
Unsurprisingly, the starting point for any ORM task is usually the database schema (there are people who start with the Objects and work “backward” to the schema, but I haven’t worked with any of them yet). In our example, we have a pristine, consistent, completely normalized schema. In other words, it’s probably nothing like you’ll ever be lucky enough to see in the real world! Here’s our simple little ERD:From this ERD, we can infer the following: 1.) An order is comprised of zero or more pizzas. 2.) A pizza is associated with one size. 3.) A pizza may be associated with a string of text containing “special instructions.” 4.) A pizza may have zero or more toppings. You probably also notice that each table has a column called version. This will be used for an optimistic locking strategy.

The first question is, “Where should we start?” There’s no right answer for this, but I find that it’s easiest to start working with the entities with the fewest dependencies. For example, you can’t have an order without a pizza, and you can’t have a pizza without a size, so maybe it makes sense to start with the size. But before that, we’ll want an ID interface.

An ID Interface
First things first. You’ll notice that, in our schema, every table has an integer ID. It’s often a good idea to have all of your objects implement the same interface for accessing the ID, because it makes it easier to create Generic DAOs (more about that in a future post). For now, let’s make a really simple interface like this:

public interface IdObject {
  public void setId(Integer id);
  public Integer getId();
}

Many-to-One Unidirectional Relationships
Now that we’ve gotten that out of the way, let’s create the Size class. It’s a simple POJO littered with annotations, like this:

@Entity
@Table(name="PIZZA_SIZE")
public class Size implements IdObject {
  @Id
  @Column(name="pizza_size_id")
  private Integer id;
 
  @Column(name="pizza_size_description")
  private String description;
 
  @Column(name="pizza_size_base_price")
  private BigDecimal basePrice;
 
  @Version @Column(name="version")
  private Integer version;
 
  public Integer getId() { return id; }
  public void setId(Integer id) { this.id = id; }
 
  public String getDescription() { return description; }
  public void setDescription(String description) { this.description = description; }
 
  public BigDecimal getBasePrice() { return basePrice; }
  public void setBasePrice(BigDecimal basePrice) { this.basePrice = basePrice; }
 
  public Integer getVersion() { return version; }
  public void setVersion(Integer version) { this.version = version; }
}

Here are some notes on the annotations that were used in the above class:
@Entity
tells the JPA provider that this is a managed object.
@Table specifies the table name. The JPA provider will attempt to default the table name to a sane value based on the class name, but I like to be explicit. I’m funny that way. Perhaps it’s OCD. Or a power-trip.
@Column indicates the name of the column, and can include other attributes about the column (you’ll see a few additional attributes later on). Again, JPA can try to default this to sane values for you, but I like to be explicit.
@Version indicates that a particular column is used for indicating when a row is updated. This column can then be used in an optimistic locking scheme.

Next, let’s do the Pizza object to show how we map a Pizza to a Size.
One thing I that always tripped me up when I started out with ORM
tools was the difference between “One-to-Many” and “Many-to-One.” I never knew, if I call a relationship many-to-one in my metadata, is this object the one that there are many of, or is it the other way around? The answer is that “this” object always comes first. ManyToOne means that “there are many of this object to one of those objects.” The “Many” side is often the side that has the foreign key.

In our case, there will be many Pizzas that are the same size. So when we make our Pizza object, we will want to use the @ManyToOne annotation. Here’s what the Pizza object looks like so far. I’ve omitted the getters and setters to save space:

@Entity
@Table(name="PIZZA")
public class Pizza implements IdObject {
  @Id
  @Column(name="pizza_id")
  private Integer id;
 
  @ManyToOne(cascade={CascadeType.ALL})
  @JoinColumn(name="pizza_size_id",nullable=false)
  private Size size;
 
  @Version @Column(name="version")
  private Integer version;
 
  // (Accessor methods omitted)
}

Note that, when we made our Size object, we did not include a reference to the Pizza. That was an intentional design decision. In this application, it’s unlikely that we will want to instantiate a Size object, and get a collection containing all of the Pizzas of that size, so we don’t bother with mapping it. This is called unidirectional association.

The @ManyToOne annotation specifies a cascade attribute. There are several different settings for this attribute, which you can read more about here. I tend to cascade the persistent state to all related objects because it reduces the amount of redundant API calls. By default, JPA does not cascade pers istence to related objects. I’ll cover the cascade attribute in future posts, but for now, we’ll go with my personal preference, because I’m writing the article!

The @JoinColumn annotation indicates the column name that defines the linkage between the Pizza and the Size. You’ll also note that we’ve included some additional attributes on our @Column and @JoinColumn annotations. The unique and nullable attributes are particularly useful if you use tools to generate schema DDL from your mappings.

One-to-Many bidirectional relationships
Both the SpecialInstruction and the Order objects are examples of One-to-Many bidirectional relationships. In the case of SpecialInstruction, it is likely that we will care about which Pizza an instruction is associated with, and likewise for the Order. A bidirectional one-to-many relationship implies that one object has a collection of other o bjects. For example, an Order has a collection of Pizzas. First, lets add an order attribute to our Pizza object:

@Entity
@Table(name="PIZZA")
public class Pizza implements IdObject {
.
.
  @ManyToOne(cascade={CascadeType.ALL})
  @JoinColumn(name="pizza_order_id",nullable=false)
  private Order order;
 
  public Order getOrder() { return order; }
  public void setOrder(Order order) { this.order = order; }
.
.
}

Next, let’s create an Order object to contain our collection of Pizzas, like this:

@Entity
@Table(name="PIZZA_ORDER")
public class Order implements IdObject {
  @Id
  @Column(name="pizza_order_id")
  private Integer id;
 
  @OneToMany(cascade={CascadeType.ALL},mappedBy="order")
  private Set pizzas = new HashSet();
 
  @Version @Column(name="version")
  private Integer version;
 
  // (version and id accessors omitted)
 
  public Set getPizzas() {  return pizzas; }
  public void setPizzas(Set pizzas) { this.pizzas = pizzas; }
  public void addPizza(Pizza pizza) {  pizza.setOrder(this);  this.pizzas.add(pizza); }
}

There are a couple of things you worth noting about this mapping:
1.) The @OneToMany annotation uses the mappedBy attribute to indicate which member of the related object defines the linkage between the two tables. In this case, we are saying that the Pizza object contains a member named order, which defines the linkage between the two objects.
2.) I’ve created a utility method called addPizza. This simplifies setting both sides of the bidirectional relationship by setting the Order object on the Pizza and adding the Pizza to the Order’s collection. Users of this class will only need to make one method call to do both.

Many-to-Many relationships via a Join Table
The last thing we’ll cover is how to map Join Tables. In our ERD, you can see that Toppings are modeled in the database with a TOPPING table that contains all of the valid toppings, a PIZZA table that contains all of the valid Pizzas, and a PIZZA_TOPPING table in the middle that maps all of the valid Pizzas to all of the valid Toppings. You could create an object called PizzaTopping that corresponds to the PIZZA_TOPPING table. Then you could have a One-to-Many relationship from the Pizza to the PizzaTopping, and a One-to-One from each PizzaTopping to a Topping. That would be very cumbersome to work with! Fortunately, there’s a better way.

Logically, a Pizza has a collection of Toppings. In our Java code, we really shouldn’t care about the fact that there is a PIZZA_TOPPING join table in the middle. First, let’s create a simple Topping class:

@Entity
@Table(name="TOPPING")
public class Topping implements IdObject {
  @Id
  @Column(name="topping_id")
  private Integer id;
 
  @Column(name="topping_description")
  private String description;
 
  @Column(name="topping_price")
  private BigDecimal price;
 
  @Version @Column(name="version")
  private Integer version;
 
  // (Accessors omitted)
}

This is how the association would be mapped in the Pizza class:

@Entity
@Table(name="PIZZA")
public class Pizza implements IdObject {
.
.
  @ManyToMany(cascade={CascadeType.ALL})
  @JoinTable(name="PIZZA_TOPPING",
             joinColumns=@JoinColumn(name="pizza_id"),
             inverseJoinColumns=@JoinColumn(name="topping_id"))
  private Set toppings = new HashSet();
 
  public Set getToppings() { return toppings; }
  public void setToppings(Set toppings) { this.toppings = toppings; }
  public void addTopping(Topping topping) { this.toppings.add(topping); }
.
.
}

The @JoinTable annotation defines three key attributes:
name: Identifies the name of the join table.
joinColumns: This attribute identifies the column name in the join table that points to this object.
inverseJoinColumns: This attribute defines the column name in the join table that points to the other objects.

From your Java code, the semantics for dealing with toppings on a pizza are just like any other set, much like you’d work with a One-to-many object.

Conclusion
Since the introduction of annotations, object/relational mapping is one of the easiest aspects of working with JPA over other frameworks. You can see this whole project in action on your IDE of choice by downloading it here (or from here if that doesn’t work for some reason). It should be a pretty reasonable starting point if you want a reference project to start playing with JPA. I hope to revisit the Pizza Shop project to cover other JPA topics in future posts.

Tags: , , , ,
Posted in blog | 8 Comments »


Glassfish to Tomcat w/ JDBC Connection Pooling

Here’s your don’t-waste-hours-on-something-silly-that-I-did tip for the day.

I recently had the opportunity to change an existing in-house web application from running under Tomcat 5.5, to Glassfish v2. The application uses JDBC connection pooling in the application server, and uses JNDI to find the pool. The only stumbling block I encountered was that, immediately after deploying the application, Hibernate would always complain that it couldn’t find the connection:

org.hibernate.HibernateException: Could not find datasource
at org.hibernate.connection.DatasourceConnectionProvider.configure(DatasourceConnectionProvider.java:56)
at org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider(ConnectionProviderFactory.java:124)
at
.
.
(yadda yadda)
.
Caused by: javax.naming.NameNotFoundException: No object bound to name java:/comp/env/jdbc/MyDB
.
.

As it turns out, the datasource that I was using in hibernate.cfg.xml was perfectly fine for Tomcat, but not for Glassfish. I had put the fully qualified JNDI file in my config file:

<property name="connection.datasource">java:/comp/env/jdbc/ApptrackDB</property>

Glassfish doesn’t like that. Once I changed it to:

<property name="connection.datasource">jdbc/ApptrackDB</property>

Everything worked swimmingly.

Tags: , , ,
Posted in blog | 2 Comments »


Build Date on a Tapestry 4 login page using Ant

Recently, I had to put a build timestamp onto a login page for a web application I’m developing at work. The web application is written using Tapestry 4.1, but some of the techniques are equally applicable to other frameworks. I thought I’d share.

First, you need to setup your ant task to grab a timestamp, and put it into your manifest file. You do so using the tstamp task, like this:

The tstamp task is taking the current date and time, formatting it as specified by pattern (just as you’d specify it in a SimpleDateFormat) and placing it in the buildtstamp variable. The manifest task builds a MANIFEST.MF file which ends up in your deployed web application’s META-INF directory. You’ll notice that I’m also putting the name of the user who built the application into the manifest.

Next, we need to read the Manifest from our application. The first screen presented by my Tapestry app is LogOn.java. First, use HiveMind to inject the ServletContext into my page:

@InjectObject(“service:tapestry.globals.ServletContext”)
public abstract ServletContext getServletContext();

Also, we need to create an abstract method into which we’ll store and retrieve the build date:

public abstract String getBuiltOn();
public abstract void setBuiltOn(String builtOn);

Finally, we need to read the Manifest file in our pageBeginRender method, and set the “Built On” date accordingly. This is how I did this:

public void pageBeginRender(PageEvent event) {ServletContext sc = this.getServletContext();String filename = sc.getRealPath("/META-INF/MANIFEST.MF");try {  BufferedInputStream i = new BufferedInputStream(new FileInputStream(filename));  Manifest m = new Manifest(i);  Attributes attrib = m.getMainAttributes();  this.setBuiltOn(attrib.getValue("Build-Date"));} catch (Exception e) {  log.warn("Unable to read MANIFEST.MF");}}

Finally, we need to actually render this on the LogOn page. I did this with a simple Insert component directly on the html page:

Built: <span jwcid=”@Insert” value=”ognl:builtOn”>

And voila! You have a build date on your log page, which can come in handy, e.g., when your QA team doesn’t know which version they’re testing!

Tags: , ,
Posted in blog | Comments Off