Posts Tagged ‘pizzashop’

Hibernate Criteria Subqueries: Exists

NOTE: Apologies for the recent blogging hiatus. I just started a new job and haven’t had a lot of time to devote to this blog lately!

While working on a recent project, I came into a situation where I needed to do an “exists” query, using a Criteria-style query. The online documentation for this feature is a little sparse, so I thought I’d share what I did.

The Pizza-shop Data Model (Again)

I keep reusing a data model for a Pizza shop in my posts, and this post will be no different. This data model first appeared in my JPA mapping tutorial. Here’s an ERD of the model again:

Find me Orders with Small Pizzas!
Given this model, what if we needed to find each order that contained a small pizza? Suppose your database had the following data:


As with my earlier posting, the object model has a PizzaOrder class that contains a Set of Pizza objects which correspond to each customer order. Your first inclination might be to do a criteria-within-a-criteria, like this:

Criteria criteria = Criteria.forClass(PizzaOrder.class);
criteria.createCriteria("pizza").add("pizza_size_id",1);
List
 ordersWithOneSmallPizza = criteria.list();

You’d be in for a bit of a surprise, though. While you might expect only two Pizza orders to be returned (namely, orders #1 and #2), you’ll actually have three orders in the result set; because order #2 has two small pizzas in it, order #2 will appear twice in your results!

The reason why this happens is pretty simple, and it becomes clear if you enable Hibernate’s SQL output feature. To locate all of the pizza orders which contain a small pizza, Hibernate needs to do an inner join to the PIZZA table. This is true regardless of whether you’ve mapped the Pizza objects to be fetched lazily; the join is required because of your query criteria, not because of your mappings. Note: it’d be really nice if Hibernate were clever enough to identify from the result set that it had duplicate PIZZA_ORDER records, and build the Set of Pizza objects accordingly, but I suspect that this would be a very difficult thing to do, so I’m not holding my breath.

The Right Way to Do It
What you’re really trying to do is to obtain all Pizza Orders where an associated small pizza exists. In other words, the SQL query that you’re trying to emulate is

SELECT *
  FROM PIZZA_ORDER
 WHERE EXISTS (SELECT 1
                 FROM PIZZA
                WHERE PIZZA.pizza_size_id = 1
                  AND PIZZA.pizza_order_id = PIZZA_ORDER.pizza_order_id)

The way that you do that is by using an “exists” Subquery, like this:

Criteria criteria = Criteria.forClass(PizzaOrder.class,"pizzaOrder");
DetachedCriteria sizeCriteria = DetachedCriteria.forClass(Pizza.class,"pizza");
sizeCriteria.add("pizza_size_id",1);
sizeCriteria.add(Property.forName("pizza.pizza_order_id").eqProperty("pizzaOrder.pizza_order_id"));
criteria.add(Subqueries.exists(sizeCriteria.setProjection(Projections.property("pizza.id"))));
List<pizzaOrder> ordersWithOneSmallPizza = criteria.list();

And voila, the result will contain two PizzaOrders!
Photo Credit: Squeaky Marmot

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 »


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 »


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 »