Re: Persistence API - magic?
nroberts wrote:
I'm a little confused about how and why the persistence API is even
being used, let alone how it works, in this tutorial I just went
through.
I followed the instructions in this tutorial:
http://programming.manessinger.com/tutorials/an-eclipse-glassfish-java-ee=
-6-tutorial/
What I'm trying to figure out is how the "entity" classes that eclipse
created with the JPA tools work so I can make my own if I need to.
One tutorial on persistence that I found (
http://www.javaworld.com/javaworld/jw-01-2008/jw-01-jpa1.html?page=3 )
explains how to make them by hand but it uses an orm.xml or
annotations to tell Java what table and what columns to connect an
entity object with. The eclipse stuff doesn't seem to do that at
all. The orm.xml file exists, but it's practically empty containing
nothing but the root element and xml tag. Here's an example entity:
@Entity
public class Zip extends com.manessinger.util.jpa.Entity implements
Serializable {
private static final long serialVersionUID = 1L;
Please, please, please do not use TAB characters to indent code on Usenet!
Use spaces, up to four per indent level.
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
private String code;
private String name;
//bi-directional many-to-one association to Country
@ManyToOne
private Country country;
// ... getters and setters...
}
I was thinking that perhaps it was order based, but the order of the
columns in the zip table to do not match. COUNTRY_ID comes between ID
and CODE. The names are close but the case is different and the
"country" column is actually COUNTRY_ID.
The manessinger Entity base doesn't have anything interesting but some
id utility functions:
public abstract class Entity {
public static boolean isId(Integer id)
{
return (id != null && id > 0);
}
public boolean hasId()
{
return isId(getId());
}
public abstract Integer getId();
}
The information doesn't seem to be at the query site either:
Query q = em.createQuery("select co from Country co");
This looks like SQL but is most definitely not SQL. It is a request to obt=
ain a collection (an object-oriented concept) of Country objects. It is no=
t a set of table rows.
result = (List<Country>)q.getResultList();
As you see in this simple example, the sensibility of JPA is object-oriente=
d. This differs significantly from the relational algebra at the heart of t=
he data-oriented sensibility of RDBMSes.
What are the rules that Java is using in order to tell what I want
here and do it? As it stands it seems to almost be intuitively
interpreting what I want to do, which I know is impossible. Why does
this code work?
It is like magic, which is both a strength and a source of potential confus=
ion.
By default the JPA mechanism matches based on the class and attribute names=
.. An entity type like 'Zip' maps to a similarly-named table, "zip". You c=
an set up the persistence.xml to have the system actually create the tables=
for you as it executes the code.
The attributes of a class, such as 'id', map to similarly-named columns in =
the table by default, e.g., "id".
As Arved pointed out, you can override these defaults with annotations. Se=
e the Java EE tutorial for details.
<http://java.sun.com/javaee/6/docs/tutorial/doc/bnbpy.html>
The persistence.xml interacts with the application server's configuration f=
iles (such as server.xml and web.xml in Tomcat) to link to a database syste=
m.
Relations are mapped to collections of objects. If you do JPA right, you a=
lmost never have to refer to an id field (in the SQL sense, an id column)_e=
xplicitly. You do have to involve the "natural" keys of your object types =
in the 'equals()' and 'hashCode()' (and as Josh Bloch and others suggest, t=
he 'toString()') methods. (Auto-generated integer surrogate keys are anath=
ema!)
JPA works best when the entity types are simple.
--
Lew