Tuesday, April 18, 2006

Java Persistence API kickstart example



The new Java Persistence API (JSR 220) - the API for management of persistence and object/relational mapping - is comming your way! Finally persistence gets standardised. The Java Persistence API, or simply JPA, is required to be supported by any Java EE 5 implementation (as part of EJB 3.0), but can also be used in stand-alone Java SE.

I've set up a simple kickstart example which can be used as starting point to persist objects and run EJBQL queries. Start experimenting yourself today! You can add your own Java objects to the example and use them to persist or retrieve data.

To keep things simple we will use the stand-alone JPA implementation of GlassFish, Toplink Essentials, in Java SE (JDK 5 required) and as database we use an embedded HSQLDB database.


  1. Let's get started by downloading the GlassFish JPA implementation from: https://glassfish.dev.java.net/downloads/persistence/JavaPersistence.html (for this example I used build 44). You need to install/unpackage the downloaded jar as described on the download page: java -jar filename.jar. A directory will be created containing the needed jar files. Next, download HSQLDB from: http://www.hsqldb.org.

  2. Create a project environment (e.g. using Eclipse) and make sure toplink-essentials.jar, toplink-essentials-agent.jar and hsqldb.jar are on the classpath.

  3. Next, create your first entity class:
    import javax.persistence.Entity;import javax.persistence.Id;



    @Entity

    public class Cat {



    private String id;

    private String name;

    private char sex;

    private float weight;



    public Cat() {

    }



    public Cat(String id, String name, char sex, float weight) {

    this.id = id;

    this.name = name;

    this.sex = sex;

    this.weight = weight;

    }



    @Id

    public String getId() {

    return id;

    }



    public void setId(String id) {

    this.id = id;

    }



    public String getName() {

    return name;

    }



    public void setName(String name) {

    this.name = name;

    }



    public char getSex() {

    return sex;

    }



    public void setSex(char sex) {

    this.sex = sex;

    }



    public float getWeight() {

    return weight;

    }



    public void setWeight(float weight) {

    this.weight = weight;

    }

    }


  4. Create a META-INF directory on your classpath and add the file persistence.xml:
    <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">

    <persistence-unit name="example">

    <!-- Provider class name is required in Java SE -->

    <provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>

    <!-- All persistence classes must be listed -->

    <class>Cat</class>

    <properties>

    <!-- Provider-specific connection properties -->

    <property name="toplink.jdbc.driver" value="org.hsqldb.jdbcDriver"/>

    <property name="toplink.jdbc.url" value="jdbc:hsqldb:mem:."/>

    <property name="toplink.jdbc.user" value="sa"/>

    <property name="toplink.jdbc.password" value=""/>

    <!-- Provider-specific settings -->

    <property name="toplink.ddl-generation" value="create-tables"/>

    <!-- other values are: drop-and-create-tablesnone -->

    <property name="toplink.logging.level" value="DEBUG"/>

    <property name="toplink.platform.class.name" value="oracle.toplink.essentials.platform.database.HSQLPlatform"/>

    </properties>

    </persistence-unit>

    </persistence>

    Because we are running HSQLDB in memory and have set ddl-generation to "create-tables" we don't have to install a database and even don't have to create the Cat table. Toplink Essentials will create the table automatically.

  5. Create a simple Example class in which we will use the Java Persistence API:
    import java.util.List;

    import javax.persistence.EntityManager;

    import javax.persistence.EntityManagerFactory;

    import javax.persistence.Persistence;



    public class Example {



    public static void main(String[] args) {



    EntityManagerFactory emf = Persistence.createEntityManagerFactory("example");

    EntityManager em = emf.createEntityManager();

    try {

    em.getTransaction().begin();



    Cat princess = new Cat("1", "Princess", 'F', 7.4f);

    Cat blackie = new Cat("2", "Blackie", 'M', 7.6f);



    em.persist(princess);

    em.persist(blackie);



    em.getTransaction().commit();



    List<Cat> cats = em.createQuery("SELECT c FROM Cat c").getResultList();

    for (Cat c : cats) {

    System.out.println(c.getName());

    }

    } catch(Exception ex) {

    em.getTransaction().rollback();

    } finally {

    em.close();

    }

    }

    }

    First we persist 2 Cat instances and later we retrieve them back againg using an EJBQL query.

  6. Now run the Example class. The result should be something like below. This means you are successfully using the Java Persistence API!
    [TopLink Info]: 2006.04.18 08:54:44.734--ServerSession(9800632)--TopLink, version: Oracle TopLink Essentials - 2006.4 (Build 060412)

    [TopLink Info]: 2006.04.18 08:54:45.093--ServerSession(9800632)--file:/C:/Projects/workspace/jpa_example-example login successful

    Princess

    Blackie


Next steps: create your own Java objects, list them in the persistence.xml and start expirementing with them by persisting them and retrieving them using EJBQL queries. Note that when you run the example new tables are created automatically for your new Java objects.

6 comments:

Mirror Spock said...

I tried to run the cat example and I get this error:

"Property toplink.logging.level has an illegal value DEBUG"

Am I doing something wrong?

Mirror Spock said...

Never mind, changing DEBUG to INFO solved the problem.

Mirror Spock said...

I got the example to run, but I am wondering just where the created database goes.

Marcel Overdijk said...

It uses an in-memory HSQLDB database defined by the toplink.jdbc.url property. This easy for experimenting etc.

Cheers,
Marcel

Anonymous said...

Hi,

I've tried your example and it worked. Thanks!

I do have a question, though. I also tried to make it work with DB2. It did. But, when I tried to add the same cat twice, a database exception was raised (obviously) so the code continued with the catch-block which tells the entity-manager to rollback. But, since there was no transaction active (it closed when the commit method was called) it raised another exception. So, wouldn't it be better not to call rollback in the catch-block?

Regards,
Pipo

Anonymous said...

Hi,

I've tried your example and it worked. Thanks!

I do have a question, though. I also tried to make it work with DB2. It did. But, when I tried to add the same cat twice, a database exception was raised (obviously) so the code continued with the catch-block which tells the entity-manager to rollback. But, since there was no transaction active (it closed when the commit method was called) it raised another exception. So, wouldn't it be better not to call rollback in the catch-block?

Regards,
Pipo