10/12/2011

Using the JPA2 in Desktop Applications

This post is based upon Database schema described in my previous article.
Here we will try to build a Domain Model for the existent DB.

We will use Maven for project creation and dependencies management, Eclipse IDE for coding, MySQl DB Server for data persistence.

1. Create project in maven


mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart

Define value for property 'groupId' - net.schastny.jpa
Define value for property 'artifactId' - desktop
Define value for property 'version' - 1.0-SNAPSHOT
Define value for property 'package' - net.schastny.jpa


2. Import Project into Eclipse


Import => Existing Maven Projects…


3. Add a plugin into pom.xml

<build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>

                <configuration>
                    <mainClass>net.schastny.jpa.App</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

Thus we can run the project.
Eclipse Main Menu => Run => Run Configurations => Maven Build => New Conf:
Base Directory: project dir
Goals: exec:java

4. Update dependencies in pom.xml

<dependencies>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>

    <!-- Hibernate -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>3.3.2.GA</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-annotations</artifactId>
        <version>3.4.0.GA</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-commons-annotations</artifactId>
        <version>3.3.0.ga</version>
    </dependency>
    
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.5.2</version>
    </dependency>
    
    <!-- MySQL driver -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>
    
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>3.3.2.GA</version>
    </dependency>
    
    <!-- JSR 303 Form Validation -->
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>1.0.0.GA</version>
    </dependency>

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>4.1.0.Final</version>
    </dependency>
</dependencies>

5. Add META-INF/persistence.xml

<persistence 
    xmlns="http://java.sun.com/xml/ns/persistence" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> 

    <persistence-unit name="company_unit">
        <properties>
            <property name="hibernate.connection.driver_class"     value="com.mysql.jdbc.Driver" />
            <property name="hibernate.connection.url"             value="jdbc:mysql://localhost:3306/company" />
            <property name="hibernate.connection.username"         value="root" />
            <property name="hibernate.connection.password"         value="" />
            <property name="hibernate.dialect"                     value="org.hibernate.dialect.MySQLDialect" />
            <property name="hibernate.show_sql"                 value="true" />
        </properties>
    </persistence-unit>
    
</persistence>

6. Domain Entities

package net.schastny.jpa.domain;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "cats")
public class Category {

    @Id
    @Column(name = "id")
    private int id;

    @Column(name = "name")
    private String name;

    @OneToMany(mappedBy = "category")
    private List<Project> projects;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public List<Project> getProjects() {
        return projects;
    }

    public void setProjects(List<Project> projects) {
        this.projects = projects;
    }

}

package net.schastny.jpa.domain;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "projects")
public class Project {

    @Id
    @Column(name = "id")
    private int id;

    @Column(name = "name")
    private String name;

    @ManyToOne
    @JoinColumn(name = "cat_id")
    private Category category;

    @ManyToMany(mappedBy = "projects")
    private List<Person> persons;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    public List<Person> getPersons() {
        return persons;
    }

    public void setPersons(List<Person> persons) {
        this.persons = persons;
    }

}

package net.schastny.jpa.domain;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

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

    @Id
    @Column(name = "id")
    private int id;

    @Column(name = "name")
    private String name;

    @ManyToMany
    @JoinTable(
            name = "ptable", 
            joinColumns         = @JoinColumn(name = "person_id", referencedColumnName = "id"), 
            inverseJoinColumns     = @JoinColumn(name = "project_id", referencedColumnName = "id"))
    private List<Project> projects;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public List<Project> getProjects() {
        return projects;
    }

    public void setProjects(List<Project> projects) {
        this.projects = projects;
    }

}

7. DAO Objects

package net.schastny.jpa.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

import net.schastny.jpa.domain.Category;

public class CategoryDAO {
 private EntityManagerFactory entityManagerFactory;

 public CategoryDAO() {
  entityManagerFactory = Persistence.createEntityManagerFactory("company_unit");
 }
 
 public void store(Category category) {
  EntityManager manager = entityManagerFactory.createEntityManager();
  EntityTransaction tx = manager.getTransaction();
  try {
   tx.begin();
   manager.merge(category);
   tx.commit();
  } catch (RuntimeException e) {
   tx.rollback();
   throw e;
  } finally {
   manager.close();
  }
 }

 public void delete(Long categoryId) {
  EntityManager manager = entityManagerFactory.createEntityManager();
  EntityTransaction tx = manager.getTransaction();
  try {
   tx.begin();
   Category category = manager.find(Category.class, categoryId);
   manager.remove(category);
   tx.commit();
  } catch (RuntimeException e) {
   tx.rollback();
   throw e;
  } finally {
   manager.close();
  }
 }

 public Category findById(Long categoryId) {
  EntityManager manager = entityManagerFactory.createEntityManager();
  try {
   return manager.find(Category.class, categoryId);
  } finally {
   manager.close();
  }
 }

 public List<Category> findAll() {
  EntityManager manager = entityManagerFactory.createEntityManager();
  try {
   Query query = manager.createQuery("select category from Category category");
   @SuppressWarnings("unchecked")
   List<Category> items = query.getResultList();
   for (Category item : items) {
    item.getProjects().size();
   }
   
   return items;

  } finally {
   manager.close();
  }
 }
 
}

package net.schastny.jpa.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

import net.schastny.jpa.domain.Project;

public class ProjectDAO {
    private EntityManagerFactory entityManagerFactory;

    public ProjectDAO() {
        entityManagerFactory = Persistence.createEntityManagerFactory("company_unit");
    }
    
    public void store(Project project) {
        EntityManager manager = entityManagerFactory.createEntityManager();
        EntityTransaction tx = manager.getTransaction();
        try {
            tx.begin();
            manager.merge(project);
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
            throw e;
        } finally {
            manager.close();
        }
    }

    public void delete(Long projectId) {
        EntityManager manager = entityManagerFactory.createEntityManager();
        EntityTransaction tx = manager.getTransaction();
        try {
            tx.begin();
            Project project = manager.find(Project.class, projectId);
            manager.remove(project);
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
            throw e;
        } finally {
            manager.close();
        }
    }

    public Project findById(Long projectId) {
        EntityManager manager = entityManagerFactory.createEntityManager();
        try {
            return manager.find(Project.class, projectId);
        } finally {
            manager.close();
        }
    }

    public List<Project> findAll() {
        EntityManager manager = entityManagerFactory.createEntityManager();
        try {
            Query query = manager.createQuery("select project from Project project");
            @SuppressWarnings("unchecked")
            List<Project> items = query.getResultList();
            for (Project item : items) {
                item.getPersons().size();
            }
            
            return items;

        } finally {
            manager.close();
        }
    }
    
}

package net.schastny.jpa.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

import net.schastny.jpa.domain.Person;

public class PersonDAO {
    private EntityManagerFactory entityManagerFactory;

    public PersonDAO() {
        entityManagerFactory = Persistence.createEntityManagerFactory("company_unit");
    }
    
    public void store(Person person) {
        EntityManager manager = entityManagerFactory.createEntityManager();
        EntityTransaction tx = manager.getTransaction();
        try {
            tx.begin();
            manager.merge(person);
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
            throw e;
        } finally {
            manager.close();
        }
    }

    public void delete(Long personId) {
        EntityManager manager = entityManagerFactory.createEntityManager();
        EntityTransaction tx = manager.getTransaction();
        try {
            tx.begin();
            Person person = manager.find(Person.class, personId);
            manager.remove(person);
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
            throw e;
        } finally {
            manager.close();
        }
    }

    public Person findById(Long personId) {
        EntityManager manager = entityManagerFactory.createEntityManager();
        try {
            return manager.find(Person.class, personId);
        } finally {
            manager.close();
        }
    }

    public List<Person> findAll() {
        EntityManager manager = entityManagerFactory.createEntityManager();
        try {
            Query query = manager.createQuery("select person from Person person");
            @SuppressWarnings("unchecked")
            List<Person> items = query.getResultList();
            for (Person item : items) {
                item.getProjects().size();
            }
            
            return items;

        } finally {
            manager.close();
        }
    }
    
}

8. Trying the Application

package net.schastny.jpa;

import java.util.List;

import net.schastny.jpa.dao.CategoryDAO;
import net.schastny.jpa.dao.PersonDAO;
import net.schastny.jpa.dao.ProjectDAO;
import net.schastny.jpa.domain.Category;
import net.schastny.jpa.domain.Person;
import net.schastny.jpa.domain.Project;

public class App {

    private CategoryDAO categoryDAO = new CategoryDAO();
    private PersonDAO     personDAO     = new PersonDAO();
    private ProjectDAO     projectDAO     = new ProjectDAO();
    
    private String formatString = "%1$-3s %2$-30s %3$s \n";

    public static void main(String[] args) {
        App app = new App();
        app.printCategoryInfo();
        app.printPersonInfo();
        app.printProjectInfo();
    }
    
    public void printCategoryInfo() {
         List<Category> catList = categoryDAO.findAll();
         System.out.printf(formatString, "Id", "Cat Name", "Projects");
         for (Category category : catList) {
             List<Project> categoryProjects = category.getProjects();
             String categoryProjectsString = " ";
             for (Project project : categoryProjects) {
                 categoryProjectsString += project.getName() + ". ";
             }
             
             System.out.printf(formatString, category.getId(), category.getName(), category.getProjects().size() + categoryProjectsString);
         }
         System.out.print("\n\n\n");
    }
    
    public void printPersonInfo() {
        List<Person> personList = personDAO.findAll();
         System.out.printf(formatString, "Id", "Person", "Projects");
         for (Person person : personList) {
             List<Project> personProjects = person.getProjects();
             String personProjectsString = " ";
             for (Project project : personProjects) {
                 personProjectsString += project.getName() + ". ";
             }
             
             System.out.printf(formatString, person.getId(), person.getName(), person.getProjects().size() + personProjectsString);
         }
         System.out.print("\n\n\n");
    }
    
    public void printProjectInfo() {
        List<Project> projectList = projectDAO.findAll();
         System.out.printf(formatString, "Id", "Project Name", "Persons");
         for (Project project : projectList) {
             List<Person> projectPersons = project.getPersons();
             String projectPersonsString = " ";
             for (Person person : projectPersons) {
                 projectPersonsString += person.getName() + ". ";
             }
             
             System.out.printf(formatString, project.getId(), project.getName(), project.getPersons().size() + projectPersonsString);
         }
         System.out.print("\n\n\n");
    }
}

Remark: Actually many of the actions described above could be done automatically by Eclipse Plugins. For instance there is possibility to create JPA Entities from an existing Database with OEPE JPA Entity Generation Wizard.

Summary

JPA is a standard persistence and object-relational mapping (ORM) framework for Java. It is a part of the EJB 3.0 specification (JSR220).

JPA is provided by the javax.persistence package.

It uses plain-old Java objects to represent items in a relational database.

It is designed to be a persistence framework for Java EE that improves on prior EJB persistence models by addressing their inherent challenges, by being less complex and lighter-weight. 

Further reading: JSR-317 Persistence Specification Final 2.0 Final Release.

3 comments:

  1. org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role. --->
    entityX.getChildEntities().size();

    ReplyDelete
  2. http://www.java-forums.org/ocpjbcd/52967-tutorial-review-jpa-entitymanager-operations-component-developer-exam.html

    ReplyDelete
  3. Carefully assign relationship owner. You should em.merge() owner entity to fill linking table with data.

    ReplyDelete