A First JPA Sample

A Simple Sample

persistence.xml – Our starting point


<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">

    <persistence-unit name="is" transaction-type="JTA">
        <jta-data-source>jdbc/pythia</jta-data-source>

        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <shared-cache-mode>NONE</shared-cache-mode>
        <properties>
            <property name="javax.persistence.schema-generation.database.action" value="create"/>
            <property name="eclipselink.logging.level" value="FINE"/>
            <property name="eclipselink.logging.parameters" value="true"/>
            <property name="eclipselink.cache.shared.default" value="false"/>
        </properties>
    </persistence-unit>

</persistence>

  • Eclipselink is used as our JPA provider
  • “javax.persistence.schema-generation.database.action” value=”create” creates database objects if not already there
  • “eclipselink.logging.level” value=”FINE” defines the Logging Level – use FINER and FINEST are the next higher levels
  • “jdbc/pythia” is our JTA datasource

Create an Entity Object

package de.thnuernberg.in.stuv.pythia.app.model;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
/**
 * Represents a human user of the system.
 */
@NamedQueries({
        @NamedQuery(
                name = "Account2.findByLoginName",
                query = "SELECT user FROM Account2 user WHERE user.loginName LIKE :loginName"
        )
})
@Entity
@Table(name = "Account2")
public class Account2 {

    /**
     * Primary key.
     */
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "accountSequence2")
    @TableGenerator(name = "accountSequence2")
    private Long id;

    @NotNull
    private String loginName;

    private String password;

    /**
     * Make sure empty constructor exist for persistence framework.
     */
    public Account2() {
    }

    public Long getId() {
        return id;
    }

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

    public String getLoginName() {
        return loginName;
    }

    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

Entity Manager related Objects

Account2Dao.java
package de.thnuernberg.in.stuv.pythia.app.model.dao;

import de.thnuernberg.in.stuv.pythia.app.model.Account2;

import javax.ejb.Stateless;
import javax.persistence.NoResultException;

/**
 * Entity access object for Account entities.
 */
@Stateless
public class Account2Dao extends AbstractDao {

    /**
     * Find an given Account by its login name.
     * @param loginName String with login name.
     * @return Account for login, null if not found.
     */
    public Account2 findAccountByLoginName(String loginName) {
        assert loginName != null;

        try {
            return entityManager.createNamedQuery("Account2.findByLoginName", Account2.class)
                    .setParameter("loginName", loginName)
                    .getSingleResult();
        } catch (NoResultException ex) {
            // if this exception occurs there was no user with given login name.
            return null;
        }  
    }
}

AbstractDao.java

package de.thnuernberg.in.stuv.pythia.app.model.dao;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 * Providing basic CRUD methods common for all entities.
 *
 * @param  Type of used Entity.
 */
public abstract class AbstractDao {

    @PersistenceContext
    protected EntityManager entityManager;

    public void create(T entity) {
        entityManager.persist(entity);
    }
}

–> Annotation Link Missing

Testing the Entity Code

package de.thnuernberg.in.stuv.pythia.app.services;
import de.thnuernberg.in.stuv.pythia.app.model.Account2;
import de.thnuernberg.in.stuv.pythia.app.model.dao.Account2Dao;
import de.thnuernberg.in.stuv.pythia.app.security.PasswordHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ejb.Stateless;
import javax.inject.Inject;

/**
 * Provides access to methods for creating, changing and deleting Accounts.
 */
@Stateless
public class SemesterService {

    private final static Logger LOGGER = LoggerFactory.getLogger(SemesterService.class);
    private Account2Dao account2Dao;

    @Inject
    public SemesterService(Account2Dao account2Dao) {
        this.account2Dao = account2Dao;
    }

    /**
     * Required by Java EE
     */
    public SemesterService() {
    }

    public Account2 retrieveAccount(String loginName) {
        return account2Dao.findAccountByLoginName(loginName);
    }

    /**
     * Get an Account by login name.
     *
     * @param  semesterId the loginName is unique in the DB
     * @return Account with the given loginName
     */
    public int retrieveSemesterData(int semesterId) {
        if(retrieveAccount("test") == null) {
            Account2 newAccount = new Account2();
            newAccount.setLoginName("test");
            newAccount.setPassword(PasswordHelper.encryptPassword("test"));
            account2Dao.create(newAccount);
            LOGGER.warn("New Test Account created");
        } else {
            LOGGER.warn("NO New Test Account was created");
        }
        return (semesterId + 1);
    }
}

Verify MYSQL database

  • After the initial Login Table account2 and its related sequence should be created automatically
mysql> use phythia_db
Database changed
mysql> select * from account2;
+-----+-----------+----------------------------------------------------------------------------------------------+
| ID  | LOGINNAME | PASSWORD                                                                                     |
+-----+-----------+----------------------------------------------------------------------------------------------+
| 301 | test      | $shiro1$SHA-256$500000$qJQrjAqPPJ1Jp6FI9Jjimw==$6GvFRlUdXMFqm/BeS0wJ9d3RzKnEP+BuxkISGoLWbMo= |
+-----+-----------+----------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

A more complexer Sample use a OneToMany Relationship

Reference