Analytics

Sunday, August 23, 2009

One to One shared primary key association in JPA with Hibernate

Overview

One of the less commonly used mappings in JPA and Hiberate is the @OneToOne mapping with a shared primary key. Conceptually this type of mapping is simple to understand. However, recently I tried to implement this relationship between two objects and ran into some petty issues. No clear example was listed on the net, so I decided to post a solution on a blog for possible reference for others.

OneToOne Shared Primary Key

A one to one shared primary key is not the most common mapping pattern, but is still used by many domain object designers. More common is the one to one mapping with a separate foreign key. A one to one shared primary key is simply where two objects have a one to one relationship where they share a primary key.

For example, let's use the prominant Person to Address example.

A Person can have one Address only, and an Address can only have one Person living in it. Let's consider Person the owner of the relationship, meaning its primary key gets generated first and essentially objectwise an Address is "set" in the Person object. A one to one shared primary key relationship would mean that a Person table does not have a FK column to Address, rather the Address table's primary key value is the same as Person, and acts as a foreign key to the Person table.



In contrast a one to one relationship with a foreign key would result in the Person table having a field like ADDRESS_ID, which acts as a foreign key to the Address table. The Person primary key generation is independent of the Address primary key. This means the primary key to Person and Address are not the same generally, but could be by coincidence.


Essentially, one to one with a shared primary key saves a column in the database and usually forces a bidirectional relationship through an ORM such as hibernate.

References and Example

When attempting to implement one to one shared mapping with JPA, I had a little trouble. The official JPA documentation does not give an example with a generated id, but only gives one where the ids are manually set. The Hibernate annotations site does the same. In addition there are a few blog postings which address the issue, but they are muddled and don't specify clearly the implementation details. Thus, I had to experiment and put together knowledge from all over to reach a solution.

In Hiberate Core (without JPA or Annotation), the concept and mapping implementation is explained nicely. 5.1.13 One-to-One.

The most informational resource was the book: Java Persistence with Hibernate - 7.1 Single Valued entity associations, pg278-282. This gave the implemenation with annotations.

In order to use a one to one with a shared primary key, ids on both sides of the object need a @GeneratedValue. The owner can use a generic generator where it gets a fresh number every time, but the other side of the one to one needs a custom hibernate extension, which is from @GenericGenerator. This grabs the primary key from the owner object and places it in the dependent object. In our example, Address will have the hibernate extension @GenericGenerator.

Person class



package com.assarconsulting.addressbook.model;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name = "PERSON")
public class Person {

@Id
@GeneratedValue
@Column(name = "PERSON_ID")
private Long id;

@Column(name = "NAME", nullable=false)
private String name;

@Column(name = "AGE", nullable=false)
private int age;

@OneToOne(cascade = CascadeType.ALL, mappedBy = "person")
private Address address;

public Person() {
}

public Person(String name, int age) {
this.name = name;
this.age = age;
}

public Long getId() {
return id;
}

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

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getStreetNumber() {
return address.getStreetNumber();
}

public String getStreetName() {
return address.getStreetName();
}

public String getCity() {
return address.getCity();
}

public String getState() {
return address.getState();
}

public String getZipCode() {
return address.getZipCode();
}

public Address getAddress() {
return address;
}

public void setAddress(Address address) {
this.address = address;
address.setPerson(this);
}

}



Address Class



package com.assarconsulting.addressbook.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;

@Entity
@Table(name = "ADDRESS")
@org.hibernate.annotations.GenericGenerator(name="person-primarykey", strategy="foreign",
parameters={@org.hibernate.annotations.Parameter(name="property", value="person")
})
public class Address {

@Id
@GeneratedValue(generator = "person-primarykey")
@Column(name = "PERSON_ID")
private Long id;

@Column(name = "STREET_NUMBER", nullable=false)
private String streetNumber;

@Column(name = "STREET_NAME", nullable=false)
private String streetName;

@Column(name = "CITY", nullable=false)
private String city;

@Column(name = "STATE", nullable=false)
private String state;

@Column(name = "ZIP_CODE", nullable=false)
private String zipCode;

@OneToOne
@PrimaryKeyJoinColumn
private Person person;

public Address() {
}

public Address(String streetNumber, String streetName, String city,
String state, String zipCode) {
super();
this.streetNumber = streetNumber;
this.streetName = streetName;
this.city = city;
this.state = state;
this.zipCode = zipCode;
}

public Long getId() {
return id;
}

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

public String getStreetNumber() {
return streetNumber;
}

public void setStreetNumber(String streetNumber) {
this.streetNumber = streetNumber;
}

public String getStreetName() {
return streetName;
}

public void setStreetName(String streetName) {
this.streetName = streetName;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

public String getState() {
return state;
}

public void setState(String state) {
this.state = state;
}

public String getZipCode() {
return zipCode;
}

public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}

public Person getPerson() {
return person;
}

public void setPerson(Person person) {
this.person = person;
}
}

Saturday, August 1, 2009

Why Hibernate does "delete all then re-insert" - its not so strange

Overview

Hibernate allows developers to interact with data from a relational database in an object-oriented fashion. This brings a lot of benefits to maintenance of development. However, hibernate is an abstraction of data which essentially is its function as an ORM, and this usually forces the developer to know hibernate's internals in order to use the tool effectively.

Maintaining collections in the object world is something every application does. Using hibernate you can manipulate colllections by adding and deleting items through the java api, and by way of mapping, hibernate takes care of generating the SQL to augment that data in the database. If the nuances of the mapping is not understood, hibernate may produce what seems like strange results. A particular instance arises when you map a List on the many side of a one to many relationship. When removing an item from the list, hibernate issues a delete statement to delete all elements, and then issue insert statements to insert everything back in except the one removed. This seems ineffecient and odd. Why not just delete the one item? Then if you change the collection type to a Set, only one delete statement is issued by itself. This article tries to explain this behavior and hopefully bring to light hibernate's internals.


Explanation by Example

The scenario described above occurs when mapping a one to many relationship with a association table. The association table stores two attributes, each of which is a foreign key to another table. In addition, the many side object is mapped with a List, but no index column is used. Hibernate recommends when using a list that an index column is used, but why exactly? The example should illuminate why hibernate recommends the index column when mapping a list. The example will show you what happens when using a list without an index column.

Example Setup

Let's set up the example. Let's say I have two classes: A and B. There is a one to many relationship from A to B, where A has many B's in a List. Using hibernate we map B with one to many and leave out the index column.

As instances of these classes, we have an A1 with 3 children and A9 with no children (just for contrasting sake). The figure below illustrates this


In the database, we have three tables. The association table maintains the relationship between A and B. No constraints are in the table for simplicity sake. (We want to focus on hibernate's behavior and worry less about enforcing integrity in the database.) Notice there is not indexed column in AB.


Here is the data in the tables:

Also notice that the list contains two B1's, as a list is capable of containing duplicates. So we code in java to delete an element from A, say the first element in the list which is B1.



a.getBList().remove(0);


So what occurs on hibernate's flush? It first issues an sql to delete all rows in the relationship table where B_ID = 1. Then it inserts all the relationships that are not supposed to be deleted!
This seems strange.
However the reason why this occurs is because hibernate supports the additional feature of a collection that is called a Bag. A bag is a collection which can have duplicates but is unordered. The best feature of a bag is that you can get the number of occurrences of an object through the API with
public int occurrences(Object o) 
With a list, there is no way to do the same without iterating through the whole list.

Thus, when a list is mapped without an indexed collection, hibernate treats in like a bag. In essence, a list which has an indexed column is an "indexed bag.

Since hibernate handles our list as a bag, it believes there could be duplicate entries in the association table. In addition it knows the items in table AB are unordered, so there is no way to tell which row should be deleted from the object in java. We asked earlier, why not just issue one delete statement. If it stopped here we would end up with:


So hibernate needs to continue and re-insert the rows it knows from java that are not supposed to be deleted. In memory, it can just look at the list after remove() was called and insert the remaining relationships. So we end up with what we wanted:



Conclusion

When using a list in hibernate an indexed column is necessary if you want efficient manipulation of adding and deleting items. With an indexed column, when you code a remove(index), hibernate can relate that index to the column in the db and even if there are duplicates, it can distinguish and delete one row. Better yet, if duplicates are not needed in your application, you can use a Set. A set requires no index column and hibernate can distinguish one row because it know a set does not have duplicates.

If you are wondering what is the purpose of a Bag, references below may answer that question.

References

http://www.discursive.com/books/cjcook/reference/collections-sect-bag.html
http://guanyu.info/blog/?p=69
https://forum.hibernate.org/viewtopic.php?t=957657
http://sites.google.com/site/xushengxiaotech/Home/hibernate-tips--efficient-usage-of-bag-for-association

Sunday, July 12, 2009

Clearing up the mud - Explaining the various "driven developments"

Overview

In recent years within the object oriented and agile community, several approaches to software design and development have materialized and are in use by professional software developers. Test Driven Design (TDD), Domain Driven Design (DDD), Behavior Driven Design (BDD) and Feature Driven Design (DDD) are some of the more well known approaches. While these philosophies all imbibe the classic agile principles of an incremental and iterative mindset to software development, they subtly differ from each other. Each approach focuses on a different aspect. This articles aims to highlight the subtle differences between the approaches and hopefully expose that knowledge so the readers can leverage key aspects of these "driven designs" in their own development.

Test Driven Development

Test Driven Development is probably the most well known development approach in the agile community today. TDD took root in the Xtreme Programming space and was notably brought into the public arena by Kent Beck's book, "Test-driven Development by Example". The focus of TDD is to write tests before you write writing code, but in an iterative manner. Robert C Martin drives home the point when he emphasizes his three Laws of TDD:
  • You are not allowed to write any production code unless it is to make a failing unit test pass.

  • You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
  • You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
These three points nicely define the rules, but they lack the intent of following these rules. The goal behind TDD is not just to write tests before so that you 1) don't forget to later or 2) run out of time or 3) you become lazy and just let it go or 4) that you are pressured to not write tests by external forces who don't see the benefit. These problems are addressed by using TDD but they are not the focus of TDD. Test Driven Development is more about the design of the code and the rhythm of the developer creating code.

TDD focus is to think about what a specific module was created to do and how it's clients expect to interact with it. The approach with TDD is aimed to get the developer to focus on the behavior of a class rather than the implementation. Thus a test is written specifying an expected behavior. Then code is written to satisfy that behavior. Another test is written with an additional behavior. Subsequently more code is written to satisfy this additional behavior. Thus, as a result you have written code to satisfy some desired behavior of a system, no more, no less. Within this rhythm of development, refactoring for cleaner code and better design can confidently take place due to the fact that a suite of tests has been developed along the way to ensure no functionality has been broken. Ron Jeffries, an XP founder refers to this habit as RefactorMercilessly

The definition of TDD is not as much about whether unit tests are written or...integration tests are written... or whether a unit test should test a class in total isolation... as much as it is about specifying the behavior of modules through executable tests and then satisfying that behavior with code. TDD guides the design of code with the added benefit of providing a safety net of regression tests to allow for refactoring.

Domain Driven Design

Eric Evan's book Domain Driven Design has become very popular in the last decade. Few teams claim to exclusively follow domain driven design, but many teams who are agile aware or keep up with the latest trends tend to adopt particular practices and philosophies from DDD.

The main goal of domain driven design is to tackle a complex domain. The premise is based on the thought that most software projects are overly complex and not understandable. This complexity is not due to the technical elements of the project such as networking, databases or platform, but rather the domain itself. The domain is defined as the core business activity of the user. In turn, the main philosophy of DDD is the primary effort for design of a complex project should be on the domain and domain logic, and complex domain designs should be based on a model.

Eric Evan's book enumerates several defined principles and practices, each of which is well thought out and applicable. In essence, that is the beauty of Evan's approach: that subtleties and gray areas of complexity become defined and named through domain driven design.

At its core there are a few distinct concepts which exemplify domain driven design.
  • ubiquitious language

  • domain model
  • knowledge rich domain

  • layered architecture

Ubiquitous language in its simplest meaning is the attempt to bridge the gap between the language of the business and languange of the system. The motive behind the ubiquitous language is that the complexity of a project can become unmanageable when a business term or concept is part of the system but is not reflected with the same language in the objects of the system. This tends to create an understanding gap between the business experts who define the behavior of the system and the developers who implement the behaviors of the system. A project that uses the concept of the ubiquitous language strives to incorporate business names, entities, and terminology into their objects.

A domain model is another fundamental base of domain driven design. A complex business domain will result in a complex software project. In order to understand the business domain and translate that knowledge into an object oriented system objects are necessary. A domain model is an attempt to capture knowledge learned about the business into objects. Note that the domain model does not have to be an exact depiction of the actual objects used in the system. Many projects maintain a "concept" domain model, which models the known entities, relationships and structure of a system. The main purpose of a domain model is to understand the business domain and build a visual depiction of knowledge so it can be shared amongst team members. It is not a detailed design diagram of the objects of the system but rather a precisely modeled understanding of the business in the form of objects. The domain model is a living diagram and is updated and maintained as understanding evolves.

A knowledge rich domain essentially means that domain objects in the system contain related behavior. Many projects follow the anemic domain pattern in which their domain objects contain data with getters and setter methods but do not contain any behavior methods. The behaviors are implemented "managers" or "controllers." DDD advocates that behaviors related to an object should be contained in that object. Several added benefits are gained from a knowledge rich domain. Behavior logic is contained in one object, often reducing duplicated code resulting in a gain in reuse. Objects are more encapsulated and follow the "tell don't ask" principle. Systems with knowledge rich domains are often more understandable and intuitive as an object manages its own data and its related behaviors can be found with that object, resulting in better maintenance.

Layered Architecture is a technique in designing software in order to separate concerns of a system, reduce coupling, and to isolate the domain layer of a system. An enterprise software system indelibly has several common concerns. A user interface accepts actions from a user, data must be saved to a database, transactions must be managed to maintain integrity of data, and business logic must be implemented. The question arises of where do all these concerns get implemented within a system. If these concerns are flattened into the presentation layer, this can lead to brittle software where one change could trickle to several areas and possibly unrelated areas of a system, thus making maintenance a headache. Changes become unintuitive to implement and scattered across a system. Layered architecture is fundamental concept not original to domain driven design, but nicely complements the idea of separating the domain layer. Evans concisely states the essence of the pattern:

Follow standard architectural patterns to provide loose coupling to the layers above. Concentrate all the code related to the domain model in one layer and isolate it from the user interface, application, and infrastructure code. The domain objects, free of the responsibility of displaying themselves, storing themselves, managing application tasks, and so forth, can be focused on expressing the domain model. This allows a model to evolve to be rich enough and clear enough to capture essential business knowledge and put it to work.


The typical breakdown of a system with layered architecture has the following layers:
  • User Interface (Presentation Layer)
  • Application Layer
  • Domain Layer
  • Infrastructure and Technical Services Layer (Persistance Layer)
A basic principle of layering is the dependencies between layers must exist in one direction, starting from the presentation layer downward. The domain layer contains most of the business logic and is mostly accessible to the other layers. Designing a behavior rich domain layer allows for
  • the UI to be free of business logic and available to concentrate on presentation logic
  • the application layer to be thin, meaning it directs flow and delegates work to domain objects. It also addresses the concerns of transaction management, security and other enterprise services
  • the infrastructure layer to focus of data related concerns such as connections to a database, CRUD operations that can be reused across various modules, and possibly ORM specific API calls such as a criteria query or abstracted SQL language (ejb-ql or hql).

Behavior Driven Development

Behavior Driven Develeopment was first coined and introduced by Dan North, now of ThoughtWorks. He explains his original ideas in the post Introducing BDD. BDD is a extension upon TDD and does not contest the fundamental values of TDD. Dave Astels, another strong proponent of BDD, explains that "Behavior Driven Development is what you are doing already if you are doing Test Driven Developement very well." The core of BDD consists of focusing the on behavior of software and defining that behavior through executable specification. The motive behing BDD was that the users of Test Driven Development tended to move away from focusing on behavior and a testing mentality would take over as tests were written.

An example of allowing a "testing mentality" to take over your test driven development process would be as follows:

  1. I create a test for class PersonService and its method findPersonByName, which is intended to retrieve a Person object who has the name "bob" from a database. Note that I intend class to use a DAO of somesort to do data retrieval.

  2. I create the PersonService, Person, and PersonDAO class.

  3. Now I get back to my test and create my necessary mocks which may be for the Person and PersonDAO class. During this process I set up those mock objects to have dummy data or for them to expect invocation calls.
At this point I have entered the mindset of "testing" and not just the behavior of my PersonService class. If I was only worried about the behavior and abstracted myself away from implementation, the first test I create would only consider that the invocation of PersonService.findPersonByName returns a Person object named "bob", regardless of the implementation. What if we extended this example to a method that didn't return anything, i.e. it returned void? Thus, we may write a test that only verifies that a mock is called. What does this really accomplish other then satisfying code coverage and validating that you called what you intended to call. These are legitimate concerns but not "behavior driven" concerns. They are more unit testing and general "testing" concerns. In my experience, I have seen tests in projects that verify mocks and all the tests pass, but since no behavior was validated through tests the system behavior was not met. Thus we had a situation where unit tests passed, but the code had a bug. This is classic verification without validatation. Basically, doing the right thing, but not doing the thing right.

Testing based on implementation knowledge can also lead brittle tests that break, due to the fact they are dependent on the structure of your code and not just the behavior. For example, if the PersonService.findPersonByName ever evolved to call another service, like maybe a logger, the test would may have to be updated to create a new mock. Thus, creating a test that finds a person now must be updated because I added a cross-cutting concern such as logging? This seems to break the "test only one thing" rule of thumb. This could trickle to hundreds of tests! This is an example of tests that are dependent on the internal object structure of a system and not the behavior.

Due to the motive of BDD, its proponents focused on correcting the false impressions of the test driven development and introduced the term "behavior driven." This led to introducing naming conventions on test classes and test methods with the intention of leading the developer to think more in terms of the behavior of the system. BDD also relaxes the constraints on only creating pure unit tests, where a class or module is tested in isolation. BDD developers often create tests which test a few modules together or one that hits the database, or a even a traditional pure unit test which is isolated. The behavior specification is what is important and is the focus, not the implementation.

An example test class exemplifying BDD conventions is below. Notice the test class name has "behavior" and the test method name has "should" :

WindowControl should close windows


public class WindowControlBehavior {

@Test
public void shouldCloseWindows() {

//Given
WindowControl control = new WindowControl("My frame");
AFrame frame = new Aframe();

//When
control.closeWindow();

//Then
ensureThat(!frame.isShowing());
}
}

Feature Driven Development

Jeff De Luca and Peter Coad are the founders of Feature Driven Development. FDD is a methodology created in the agile spirit and ment to address the problems of the traditional waterfall process. Overall, it is a management methodology for software, but it also contains a few integrated ideas in the realms of requirements analysis and domain modeling. The sum of its ideas creates a methodology that is structured and easy to follow. It is a simple, iterative, and well defined process.

FDD is defined by these simple steps

  1. Develop an overall model
  2. Build a features list
  3. Plan by feature
  4. Design by feature
  5. Build by feature
The first 3 steps are considered the "startup phase" and the last 2 steps are done iteratively until the project is complete. The last 2 steps are considered the "construction phase". Of course if the first three steps need to be revisited in the middle of the project, the agile spirit of FDD considers this necessary. The image below illustrates the process.

Step 1 "Develop an overall model" asserts that a project should spend sufficient time developing a domain model for the problem attempting to be solved. This borrows elements from domain driven design, and well as traditional object modeling. This exercise facilitates understanding between managers, business members, and developers. It also well defines the problem and domain.

The most homegrown characteristic of FDD is the concept of a feature. A feature is defined as a bite size chunk of functionality that is described in compact form, preferrably in one sentence. The requirements aspect of FDD is focused on features and is most relevant in step 2 "Build a feature list." Analysis and communication must be done with a customer to generate a feature list which is of course full of features. Each feature should follow the template

[action][result][object]

Example features are:
  • Calculate the total amount of a Sale
  • Display the history of all user comments
Feature Driven Design blend aspects of several agile methodologies to form a simple yet effective model for constructing complex software. The well defined concept of a feature breaks requirements down into manageable portions and allows for customer input on priority and feedback. Many tools exist centered around management of requirements in the form of features and can be used to effectively run a project.

Conclusion

Although the various "driven designs" or "driven developments" may sound the same initially, there are subtle differences to each once the details are explored. In my experience, if a project has mindful team members that are familiar with one or more of these approaches, various practices and principles are adopted within the project. Rarely does a project purely and dogmatically adopt one single approach. Most of the time various team members bring differing expertise and experience, thus the project becomes an amalgamation of several methodologies, but still upholds the agile spirit.

To be more concrete, early in my career I was on a small project that first explored agile principles. Feature Driven Development was the approach that most fit our goals and we followed the process. However, as we learned more about various approaches such as Domain Driven Design and Test Driven Development, we integrated practices such as maintaining the domain model and a test first development strategy. In fact the whole project was done under the umbrella of RUP, the Rational Unified Process, a more tradional methodology! Thus you can see that each project should consider its own needs and adopt what is best for success.

What practices have you used on your projects? Which ones do you find the most effective?

References

Presentation - Plano Java Mug - Sept 12, 2009
Clearing the Mudd

DDD
Layered Architecture
Domain Driven Design Community

FDD
Feature Driven Development Overview Presentation
Feature Driven Development (FDD) Methodology

BDD
Introducing BDD
Behavior Driven Design Community


What Drives Design