Persisting objects
Persisting transient objects may be achieved in various ways. JDBC™ allows to store and retrieved object values.
Having larger projects these tasks become increasingly tedious. It is thus desired to automate these tasks while still using JDBC™ for the low level transport layer.
The following sections start with a single class
hibintro.v1.model.User
:
User
class. Todo: Ref/Fig/classUser.fig
Object relational mapping (ORM) denotes the process of mapping instances of classes to relational table data. In our current example we may draw a simple implementation sketch:
Todo: Ref/Fig/mapUser.fig
This is far too simplistic. What about integrity constraints?
Todo: Ref/Fig/mapUserIntegrity.fig
We start with the following
hibintro.v1.model.User
class lacking integrity
constraints completely:
package hibintro.v1.model;
@Entity
public class User {
String uid;
public String getUid() {return uid;}
public void setUid(String uid) {this.uid = uid;}
String cname;
public String getCname() {return cname;}
public void setCname(String cname) {this.cname = cname;}
/**
* Hibernate/JPA require a default constructor. It has has to be implemented
* if any non-default constructor has been defined
*/
public User() {}
/**
* @param uid See {@link #getUid()}.
* @param cname See {@link #getCname()}.
*/
public User(String uid, String cname) {
this.uid = uid;
this.cname = cname;
}
}
Persisting objects with Hibernate requires a
org.hibernate.Session
instance ❶. It happens between the start ❷ and commit ❸ of a transaction being derived from that
session:
package hibintro.v1.run;
...
public class PersistSingleUser {
public static void main(String[] args) {
final org.hibernate.Session
session ❶= HibernateUtil.createSessionFactory("hibernate.cfg.xml").openSession();
final org.hibernate.Transaction
transaction = session.beginTransaction();❷
final hibintro.v1.model.User
u = new User("goik", "Martin Goik");
session.save(u);
transaction.commit(); ❸
}
}
Executing the above code yields a runtime exception:
Exception in thread "main" java.lang.ExceptionInInitializerError
at myhibernate.intro.run.PersistUser.main(PersistUser.java:14)
Caused by: org.hibernate.AnnotationException: No identifier specified for entity: myhibernate.intro.model.User
...
at myhibernate.intro.util.HibernateUtil.buildConfiguration(HibernateUtil.java:17)
at myhibernate.intro.util.HibernateUtil.<clinit>(HibernateUtil.java:9)
This runtime error is a little bit cryptic. The missing
“identifier” refers to the absence of a primary key
definition already mentioned in Figure 934, “Annotating integrity constraints ”. We define a key by annotating
the uid
property with a
javax.persistence.Id
annotation ❶:
package hibintro.v1.model;
import javax.persistence.Entity;
import javax.persistence.Id;
...
@Entity public class User {...
@Id ❶
public String getUid() {
return uid;
} ...
The careful reader will have noticed that we've annotated the
getter method rather than the property uid
itself.
Hibernate / JPA can work both ways. Annotating a
getter however offers additional support e.g. when logging for
debugging purposes is required.
This time we are successful. Since we enabled the logging of SQL
statements in Figure 929, “A basic persistence.xml
JPA configuration file. ” Hibernate
shows us the corresponding INSERT
statement:
Hibernate:
insert
into
User
(cname, uid) sky
values
(?, ?)
Notice the (?,?) part of our log: This indicates the internal
usage of JDBC™
java.sql.PreparedStatement
instances. Hibernate
generates the following create table statement:
hibintro.v1.model.User
. CREATE TABLE User (
uid VARCHAR(255) NOT NULL PRIMARY KEY,
cname VARCHAR(255)
)