7.3. The Simple Model Module
The first thing most enterprise projects need is an object model. An
object model captures the core set of domain objects in any system. A
banking system might have an object model which consists of
Account
, Customer
, and Transaction
objects, or a system to
capture and communicate sports scores might have a Team
and a Game
object. Whatever it is, there’s a good chance that you’ve modeled the
concepts in your system in an object model. It is a common practice in
Maven projects to separate this project into a separate project which
is widely referenced. In this system we are capturing each query to
the Yahoo Weather feed with a Weather
object which references four
other objects. Wind direction, chill, and speed are stored in a Wind
object. Location data including the zip code, city, region, and
country are stored in a Location
class. Atmospheric conditions such
as the humidity, maximum visibility, barometric pressure, and whether
the pressure is rising or falling are stored in an Atmosphere
class. A textual description of conditions, the temperature, and the
date of the observation is stored in a Condition
class.
The pom.xml
file for this simple object model contains one
dependency that bears some explanation. Our object model is annotated
with Hibernate Annotations. We use these annotations to map the model
objects in this model to tables in a relational database. The
dependency is org.hibernate:hibernate-annotations:3.3.0.ga
. Take a
look at the pom.xml
shown in simple-model pom.xml, and
then look at the next few examples for some illustrations of these
annotations.
simple-model pom.xml.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sonatype.mavenbook.multispring</groupId>
<artifactId>simple-parent</artifactId>
<version>1.0</version>
</parent>
<artifactId>simple-model</artifactId>
<packaging>jar</packaging>
<name>Simple Object Model</name>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.3.0.ga</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>3.3.0.ga</version>
</dependency>
</dependencies>
</project>
In src/main/java/org/sonatype/mavenbook/weather/model
, we have
Weather.java
, which contains the annotated Weather
model
object. The Weather
object is a simple Java bean. This means that we
have private member variables like id
, location
, condition
,
wind
, atmosphere
, and date
exposed with public getter and setter
methods that adhere to the following pattern: if a property is named
name
, there will be a public no-arg getter method named getName()
,
and there will be a one-argument setter named setName(String name)
.
Although we show the
getter and setter methods for the id
property, we’ve omitted most of
the getters and setters for most of the other properties to save a few
trees. See Annotated Weather Model Object.
Annotated Weather Model Object.
package org.sonatype.mavenbook.weather.model;
import javax.persistence.*;
import java.util.Date;
@Entity
@NamedQueries({
@NamedQuery(name="Weather.byLocation",
query="from Weather w where w.location = :location")
})
public class Weather {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
@ManyToOne(cascade=CascadeType.ALL)
private Location location;
@OneToOne(mappedBy="weather",cascade=CascadeType.ALL)
private Condition condition;
@OneToOne(mappedBy="weather",cascade=CascadeType.ALL)
private Wind wind;
@OneToOne(mappedBy="weather",cascade=CascadeType.ALL)
private Atmosphere atmosphere;
private Date date;
public Weather() {}
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
// All getter and setter methods omitted...
}
In the Weather
class, we are using Hibernate annotations to provide
guidance to the simple-persist
project. These annotations are used
by Hibernate to map an object to a table in a relational
database. Although a full explanation of Hibernate annotations is
beyond the scope of this chapter, here is a brief explanation for the
curious. The @Entity
annotation marks this class as a persistent
entity. We’ve omitted the @Table
annotation on this class, so
Hibernate is going to use the name of the class as the name of the
table to map Weather
to. The @NamedQueries
annotation defines a
query that is used by the WeatherDAO
in simple-persist
. The query
language in the @NamedQuery
annotation is written in something
called Hibernate Query Language (HQL). Each member variable is
annotated with annotations that define the type of column and any
relationships implied by that column:
-
Id
-
The
id
property is annotated with @Id
. This marks the id
property as the property that contains the primary key in a
database table. The @GeneratedValue
controls how new primary key
values are generated. In the case of id
, we’re using the
IDENTITY
GenerationType
, which will use the underlying
database’s identity generation facilities.
-
Location
-
Each
Weather
object instance corresponds to a Location
object. A Location
object represents a zip code, and the
@ManyToOne
makes sure that Weather
objects that point to the
same Location
object reference the same instance. The cascade
attribute of the @ManyToOne
makes sure that we persist a
Location
object every time we persist a Weather
object.
-
Condition
, Wind
, Atmosphere
-
Each of these objects is mapped as a
@OneToOne
with the
CascadeType
of ALL
. This means that every time we save a
Weather
object, we’ll be inserting a row into the Weather
table, the Condition
table, the Wind
table, and the
Atmosphere
table.
-
Date
-
Date
is not annotated. This means that Hibernate is going to use
all of the column defaults to define this mapping. The column name
is going to be date
, and the column type is going to be the
appropriate time to match the Date
object.
Note
If you have a property you wish to omit from a table mapping,
you would annotate that property with @Transient
.
Next, take a look at one of the secondary model objects, Condition
,
shown in simple-model’s Condition Model Object.. This class also resides
in src/main/java/org/sonatype/mavenbook/weather/model
.
simple-model’s Condition Model Object.
package org.sonatype.mavenbook.weather.model;
import javax.persistence.*;
@Entity
public class Condition {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
private String text;
private String code;
private String temp;
private String date;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="weather_id", nullable=false)
private Weather weather;
public Condition() {}
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
// All getter and setter methods omitted...
}
The Condition
class resembles the Weather
class. It is annotated
as an @Entity
, and it has similar annotations on the id
property. The text
, code
, temp
, and date
properties are all
left with the default column settings, and the weather
property is
annotated with a @OneToOne
annotation and another annotation that
references the associated Weather
object with a foreign key column
named weather_id
.