How do I enable statistics with Hibernate and JPA?

You can enable Hibernate statistics by setting the property hibernate.generate_statistics in the persistence.xml of your application:

<property name="hibernate.generate_statistics">true</property>

For Hibernate native application, you need to include the above property in hibernate.cfg.xml

After deploying the application, you will see in your server logs the following statistics when the Hibernate session is closed:

18:16:30,502 INFO  [org.hibernate.engine.internal.StatisticalLoggingSessionEventListener] (default task-1) Session Metrics {
    1238468 nanoseconds spent acquiring 1 JDBC connections;
    43165 nanoseconds spent releasing 1 JDBC connections;
    1692719 nanoseconds spent preparing 1 JDBC statements;
    240264 nanoseconds spent executing 1 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    276583 nanoseconds spent executing 1 flushes (flushing a total of 1 entities and 0 collections);
    44000 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)

It is also possible to gather statistics from WildFly Command Line Interface by digging into the jpa subsystem of your deployment unit. Example:

/deployment=jpa-basic.war/subsystem=jpa/hibernate-persistence-unit=jpa-basic.war#primary:read-resource(include-runtime=true)
{
    "outcome" => "success",
    "result" => {
        "close-statement-count" => 0L,
        "collection-fetch-count" => 0L,
        "collection-load-count" => 0L,
        "collection-recreated-count" => 0L,
        "collection-remove-count" => 0L,
        "collection-update-count" => 0L,
        "completed-transaction-count" => 2L,
        "connect-count" => 3L,
        "enabled" => true,
        "entity-delete-count" => 0L,
        "entity-fetch-count" => 0L,
        "entity-insert-count" => 1L,
        "entity-load-count" => 1L,
        "entity-update-count" => 0L,
        "flush-count" => 2L,
        "hibernate-persistence-unit" => "jpa-basic.war#primary",
        "optimistic-failure-count" => 0L,
        "prepared-statement-count" => 3L,
        "query-cache-hit-count" => 0L,
        "query-cache-miss-count" => 0L,
        "query-cache-put-count" => 0L,
        "query-execution-count" => 1L,
        "query-execution-max-time" => 2L,
        "query-execution-max-time-query-string" => "FROM SimpleProperty",
        "scoped-unit-name" => "jpa-basic.war#primary",
        "second-level-cache-hit-count" => 0L,
        "second-level-cache-miss-count" => 0L,
        "second-level-cache-put-count" => 0L,
        "session-close-count" => 3L,
        "session-open-count" => 3L,
        "statistics-enabled" => true,
        "successful-transaction-count" => 3L,
        "collection" => undefined,
        "entity" => {"com.mastertheboss.model.SimpleProperty" => undefined},
        "entity-cache" => {"com.mastertheboss.model.SimpleProperty" => undefined},
        "query-cache" => {"FROM_space_SimpleProperty" => undefined}
    }
}

The above statistics can also be accessed from JConsole through the jboss.as / <deployment> / jpa / <deployment>#<persistence-unit>. See the following picture:

Enabling Hibernate statistics Programmatically

Finally, it is also possible to enable live statistics programmatically using the Statistics Interface:

Statistics stats = sessionFactory.getStatistics();

stats.setStatisticsEnabled(true);

Transaction tx = session.beginTransaction();

List<Customer> c = session.createQuery("from Customer").list();

for(Customer c : customers){

System.out.println(c);

}

stats.getSessionOpenCount();

stats.logSummary();

session.close();

Configuring Composite Primary key in JPA applications

Composite keys are a group of columns in the database, whose values together make a unique value. When using Hibernate or JPA applications there are two main strategies to map a Composite Primary Key.

Mapping a Composite key with an @IdClass

The name of the class is indicated as the value of the class attribute of the IdClass element, as
shown in this example:

@Entity
@IdClass(PersonId.class)
public class Person {

	@Id
	String name;
	@Id
	String surname;
	String address;
	String email;

    // Getter Setters and Constructors
}

As you can see, the Compound keys are annotated with @Id and we need to provide an @IdClass:

public class PersonId implements Serializable {
    String name;
    String surname;

   // Constructors
   // Getters /Setters equals and hashcode

    public PersonId(String name, String surname) {
        this.name = name;
        this.surname = surname;
    }
}

If using a Repository pattern to access your data, the compound key will be used as Type (instead of the Integer id field):

public interface PersonRepository extends CrudRepository<Person, PersonId> {

    List<Person> findBySurname(String surname);
}

Mapping a Composite key with an EmbeddedId

An embedded type is marked as such by adding the @Embeddable annotation to the class definition.
This annotation serves to distinguish the class from other regular Java types. Once a class has been
designated as embeddable, then its fields and properties will be persistable as part of an entity.

Here is a Class which uses an @Embeddable annotation:

@Entity
public class Customer {
	
    @EmbeddedId
    private CustomerEmbeddable customerPK;
 
    String address;
    String email;

   // Getter Setters and Constructors
   
}

As you can see, the compound key fields are not included in the Entity class. The CustomerEmbeddable class follows here:

@Embeddable
public class CustomerEmbeddable implements Serializable {
    String name;
    String surname;

   // Constructors
   // Getters /Setters  equals and hashcode

    public CustomerEmbeddable(String name, String surname) {
        this.name = name;
        this.surname = surname;
    }
}

You should as well adapt your Repository class to use the Embeddable primary key:

public interface CustomerRepository extends CrudRepository<Customer, CustomerEmbeddable> {

    List<Customer> findByEmail(String email);
}

So, which one should you choose? from the Database point of view, no changes are required when choosing one strategy or another

The @EmbeddedId strategy does not include the primary key fields in the Entity and thus communicates more clearly that the key is a composite key. Therefore, if you are using directly your Entity in your Controllers it makes more sense to use it. On the other hand, if using a DTO layer to hide the complexity of the Entity you can opt for the @IdClass which has the advantage to be less verbose when using HQL queries.

For example, compare:

select p.name from Person p

With:

select c.customerEmbeddable.name from Customer c

In conclusion, we have covered the two main strategies to map a compound primary key in a Hibernate / JPA application.

Source code for this example: https://github.com/fmarchioni/masterspringboot/tree/master/jpa/composite-pk

JPA vs Hibernate in a nutshell

A fairly common question for developers approaching Object Relational Mapping (ORM) tools like Hibernate is what is the difference between Hibernate and JPA.

In this article we are going to explain it in a nutshell.

  • From an high level view, JPA is just like an interface without a concrete implementation of it.
  • On the other hand, Hibernate is an Object Relational Mapping (ORM) tool and also a JPA Provider which has the implementation of the functions in JPA. It can also have some extra functions which might not be there in JPA.

It follows, that you can use Hibernate as standalone product and, behind the hoods, as JPA Provider.

On the other hand, to be able to use JPA you have to choose a valid Provider. Each vendor adopts a JPA implementation. For example, WildFly (or JBoss EAP) uses Hibernate as JPA Provider. Therefore WildFly (and JBoss EAP) bundles Hibernate.

When using Hibernate vs JPA

In order to include new features in JPA, a specification needs to be voted and updated, therefore Hibernate will always include newer features as it is a more agile project.

For example, some features which are implemented in Hibernate but are still not available in JPA are:

  • Extended identifier generators (hi/lo, pooled, pooled-lo)
  • Custom CRUD SQL Statements (@SQLInsert, @SQLUpdate, @SQLDelete)
  • Adding Collection filters (e.g. @FilterDef, @Filter, @Where) and Entity filters (e.g. @Where)
  • Mapping properties to SQL fragments (e.g. @Formula)
  • Immutable entities (e.g. @Immutable)
  • Querying the second-level cache by the natural key of a given entity
  • Entity-level cache concurrency strategies (e.g. Cache(usage = CacheConcurrencyStrategy.READ_WRITE))
  • Exclude fields from optimistic locking check (e.g. @OptimisticLock(excluded = true))
  • Version-less optimistic locking (e.g. OptimisticLockType.ALL, OptimisticLockType.DIRTY)
  • Support for skipping (without waiting) pessimistic lock requests
  • Support for multi tenancy
  • Support for soft delete (e.g. @Where, @Filter)

In such cases, you can extend the power of your JPA applications by using the required Hibernate extension.

For example, in the following article, we have covered how to use Custom CRUD SQL Statements (@SQLInsert, @SQLUpdate, @SQLDelete) in a JPA application: Using custom SQL for Hibernate CRUD Operations

Hibernate vs JPA: configuration

As far as configuration is concerned, a JPA application uses a configuration file named persistence.xml which defines the Persistence units, the Provider, the Datasource to be used and may also Map Entity Objects and Properties

<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_2_0.xsd"
	version="2.0">
	<persistence-unit name="unit01"
		transaction-type="RESOURCE_LOCAL">
		<description>JPA Demo</description>
		<provider>org.hibernate.ejb.HibernatePersistence</provider>

		<!-- Mapping of classes. -->
		<class>com.sample.jpa.book.Book</class>
		<class>com.sample.jpa.book.Author</class>
		<class>com.sample.jpa.book.BookCategory</class>
                
                <jta-data-source>java:jboss/datasources/KitchensinkQuickstartDS</jta-data-source>
		<!-- Setting of Hibernate ORM Properties. -->
		<properties>
			<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
			<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
			<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/test" />
			<property name="hibernate.connection.username" value="root" />
			<property name="hibernate.connection.password" value="himserver" />
			<property name="hibernate.hbm2ddl.auto" value="update" />
			<property name="hibernate.show_sql" value="true" />
			<property name="hibernate.format_sql" value="true" />
		</properties>
	</persistence-unit>
</persistence>

On the other hand, Hibernate relies on the hibernate.cfg.xml file to map database Tables with Entity objects and to specify Connection properties:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC 
  "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
  "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
  <hibernate-configuration>
    <session-factory>
      <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
      <!-- property name="connection.driver_class">com.mysql.jdbc.Driver</property -->
      <property name="connection.url">jdbc:mysql://localhost/hibernate_examples</property>
      <property name="connection.username">user</property>
      <property name="connection.password">password</property>
      <property name="connection.pool_size">10</property>
      <property name="dialect">org.hibernate.dialect.MySQL8Dialect</property>
      <property name="current_session_context_class">thread</property>
      <property name="show_sql">true</property>
      <property name="format_sql">true</property>
      <property name="hbm2ddl.auto">update</property>
      <!-- mapping  class="com.sample.Book" / -->
  </session-factory>
</hibernate-configuration>

So, as a basic rule of thumb, if you are using JPA application, configure your persistence settings in persistence.xml applications.

On the other hand, if you are running Hibernate standalone applications configure the persistence settings in hibernate.cfg.xml.

Hibernate vs JPA: managing persistence

Unless you are relying on Hibernate extensions which are not available in JPA, you will be using the classes in the javax.persistence package (or jakartaee if using Jakarta EE 9).

As a matter of fact, to manage the persistence with JPA, we retreive the EntityManagerFactory and EntityManager, all situated in javax.persistence package.

import org.jboss.as.quickstarts.kitchensink.model.Member;

import javax.ejb.Stateless;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import java.util.logging.Logger;

// The @Stateless annotation eliminates the need for manual transaction demarcation
@Stateless
public class MemberRegistration {

    @Inject
    private Logger log;

    @Inject
    private EntityManager em;

    @Inject
    private Event<Member> memberEventSrc;

    public void register(Member member) throws Exception {
        log.info("Registering " + member.getName());
        em.persist(member);
        memberEventSrc.fire(member);
    }
}

On the other hand, Hibernate uses its own classes to represent persistence context, such as the org.hibernate.SessionFactory. As an example, assuming hiberante.cfg.xml is in the classpath, you can retrieve the SessionFactory as follows

public static Session getSessionFromConfig() {

  Configuration config = new Configuration();
  config.configure();
  SessionFactory sessionFactory = config.buildSessionFactory();
  Session session = sessionFactory.getCurrentSession();
  return session;
}

If required, you can still access Hibernate’s Session Factory in a JPA applications by using the entityManager.unwrap method, once you have retrieved the Entity Manager:

public static SessionFactory getCurrentSessionFromJPA() {
  EntityManagerFactory emf = 
      Persistence.createEntityManagerFactory("my-em-factory");
  EntityManager entityManager = emf.createEntityManager();
  Session session = entityManager.unwrap(org.hibernate.Session.class);
  SessionFactory factory = session.getSessionFactory();
  return factory;
}

Using native Queries with Hibernate and JPA

What are your options if your Hibernate/EJB application has to deal with a very complex and DB-optimized SQL query ? good interview question….
Hibernate has a built-in object oriented language for querying objects called HQL. This language is quite complete and efficient, so in theory you could translate every SQL query in its equivalent HQL ( and provide the necessary POJOs and configuration files).However the cost of translating very complex queries can be excessive (including the time spent to build all POJOs which are involved in the query). You might be very smart with HQL but it’s still very difficult that you can achieve the same performance of a Query that a DBA spent hours in order to optimize it.

This can be especially true if you are migrating an older JDBC application which has already a stable and tuned list of queries.

In these situations it is convenient to use the native SQL for creating Entity Queries.

The simplest way to run a native SQL Query is to use the createNativeQuery() method of the EntityManager interface, passing in the query string and the entity type that will be returned.

public List<Customer> findAllCustomersNative() {
        Query query = em.createNativeQuery("SELECT * from customer",Customer.class);
        List<Customer> customerList = query.getResultList();
        return customerList;
}

Native SQL can also be used for named queries by defining a @NamedNativeQuery annotation.

Let’s see an example of it:

package com.example.samplewebapp;


import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
@Entity
@NamedNativeQueries({

    @NamedNativeQuery(
        name = "Person.findAllPersons",
        query =
            "SELECT * " +
            "FROM Person ", resultClass = Person.class
    ),

    @NamedNativeQuery(
        name = "Person.findPersonByName",
        query =
            "SELECT * " +
            "FROM Person p " +
            "WHERE p.name = ?", resultClass = Person.class)
    
})
public class Person {


    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    Long id;
    String name;
    String surname;


    // Getter and Setters omitted for brevity

}

In this example, we have defined two @NamedNativeQuery:

  • Person.findAllPersons: to return all Person Entities
  • Person.findPersonByName: to return all Person Entities filtered by name

Like JP QL named queries, the name of the query must be unique within the persistence unit. If the result type is an entity, the resultClass element may be used to indicate the entity class. If the result requires a SQL mapping, the resultSetMapping element may be used to specify the mapping name.

So it’s pretty obvious how to define a @NamedNativeQuery. Now let’s check how to run the @NamedNativeQuery. There are mainly two ways:

Using the EntityManager to run the @NamedNativeQuery

If you are using the EntityManager interface to extract your data, then you can simply reference the @NamedNativeQuery from within the “createNamedQuery” as you can see in this example:

@RestController
public class PersonController {
    @PersistenceContext
    EntityManager em;
    

    @RequestMapping("/findNames")
    public List<Person> findAll() {
        
        Query q = em.createNamedQuery("Person.findAllPersons");      
        return q.getResultList();
        
    }

    @RequestMapping("/findByName/{name}")
    public List<Person> findOne(@PathVariable String name) {
        Query q = em.createNamedQuery("Person.findPersonByName");      
        q.setParameter(1, name);
        return q.getResultList();

    }
}

You can test the above REST methods:

$ curl -s http://localhost:8080/findNames | jq
[
  {
    "id": 1,
    "name": "Jack",
    "surname": "Smith"
  },
  {
    "id": 2,
    "name": "Joe",
    "surname": "Black"
  },
  {
    "id": 3,
    "name": "Martin",
    "surname": "McFly"
  }
]


$ curl -s http://localhost:8080/findByName/Jack | jq
[
  {
    "id": 1,
    "name": "Jack",
    "surname": "Smith"
  }
]

Using Spring Data Repository interface

Spring Data JPA is able to bind automatically your NamedNativeQuery in your Repository definition. Doing that is extremely simple if you follow Spring Data’s naming convention. The name of your query has to start with the name of your entity class, followed by “.” and the name of your repository method.
In our example, the method Person.findAllPersons will be mapped with the findAllPersons method and the Person.findPersonByName will be mapped as findPersonByName(String name).

public interface PersonRepository extends CrudRepository<Person, Long> {

     List<Person> findAllPersons(); 
     List<Person> findPersonByName(String name);
     
}

When running the Main application class, we can reference our Repository interface and access data without the mediation of the EntityManager:

@SpringBootApplication
public class DemoApplication {
    private static final Logger log = LoggerFactory.getLogger(DemoApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
    @Bean
    public CommandLineRunner demo(PersonRepository repository) {
        return (args) -> {
            // save a couple of persons
            repository.save(new Person("Jack","Smith"));
            repository.save(new Person("Joe","Black"));
            repository.save(new Person("Martin","McFly"));


            // fetch all persons
            log.info("Persons found with findAll():");
            log.info("-------------------------------");
            for (Person person : repository.findAllPersons()) {
                log.info(person.toString());
            }
            log.info("");



            // fetch persons by last name
            log.info("Person found with findByName('Jack'):");
            log.info("--------------------------------------------");
            repository.findPersonByName("Jack").forEach(smith -> {
                log.info(smith.toString());
            });

            log.info("");
        };
    }
}

We have just covered how to use the @NamedNativeQuery to execute native SQL statement from your Hibernate/JPA applications.
https://github.com/fmarchioni/masterspringboot/tree/master/jpa/native-query

3 ways to set a Query timeout for JPA / Hibernate applications

Most databases support statements to limit the duration of a SQL query. For example, with PostgreSQL you can set:

SET statement_timeout = 10000;

When running ORM Tools like Hibernate or JPA, there are unified ways to set a timeout for queries. Besides, you can also set a timeout limit to lock tables when using pessimistic locks. Let’s see in this tutorial which are the three ways to set a Query timeout with JPA / Hibernate.

Continue reading 3 ways to set a Query timeout for JPA / Hibernate applications

Java Persistence (JPA) with JBoss and WildFly

A major enhancement in EJB technology is the addition of the new Java Persistence API (JPA), which simplifies the Entity persistence model and adds capabilities that were not in EJB 2.1 technology. The Java Persistence API draws on ideas from leading persistence frameworks and APIs such as Hibernate, Oracle TopLink, and Java Data Objects (JDO), and well as on the earlier EJB container-managed persistence.

With Java EE 5, most of the XML configurations have been relegated to annotations.

Like the SLSB, the Entity is going to be a POJO, which will help provide us the most flexibility when creating the domain there. The Entity will look like a regular JavaBean representing a table in the database. Each of the properties will be assumed to be a persistable column on the database. This will then allow us to use EntityManager (which we will discuss in a bit) to perform operations on it that will be translated to our table.

EntityManager can be called from any class, but preferably we would want to call it from a Session Bean implementing the well famous Session Facade pattern.

So take for example the Class Note which contains some information about a trouble ticketing system

package com.sample;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "NOTE")

public class Note implements Serializable {
long noteId;

String text;

String actor;

String attachment;

@Id
@GeneratedValue
public long getNoteId() {
 return noteId;
}

public void setNoteId(long noteId) {
 this.noteId = noteId;
}

public String getActor() {
 return actor;
}

public void setActor(String actor) {
 this.actor = actor;
}

public String getAttachment() {
 return attachment;
}

public void setAttachment(String attachment) {
 this.attachment = attachment;
}

public String getText() {
 return text;
}

public void setText(String text) {
 this.text = text;
}
}

Here you can see a few annotations: at fist the Entity annotation which declares the Bean as Entity Bean. Then we have the Table annotation which is not mandatory but usually useful because naming conventions for DB Tables and Java classes usually don’t collide. Let’s go on: The @Id annotations defines the field as the primary key of the table: s.

What’s the right place for the @Id tag ? You can either add the annotation above the class field or on the getter method of the field. If you place it on the setter method it will be ignored.

Along with the @Id there’s the @GeneratedValue annotation. This is used with the @Id annotation when you have a value that is generated. The following are the types of strategies allowed (the default is AUTO):

  • AUTO: Indicates that the database should automatically pick the appropriate type
  • TABLE: Indicates that the database should have an underlying table referencing this unique ID
  • IDENTITY: Indicates that the database should use this field as an identity column
  • SEQUENCE: Indicates that the database should use a sequence column to get the column

If you need an example of an Entity structured with a Sequence here’s one short tutorial . Aren’t we forgetting something ? what about column name mappings ? well as default the Container will try to map the EJB field with Database table name if they are the same. However, if you need to have a different name, you can use the @Table annotation.
So if your text field were named TICKETTEXT in your table , your class would look like:

@Column(name="TICKETTEXT")
  public String getText() {
  return text;
}

How do you connect to your DataSource?

Just write a simple file named persistence.xml file which defines the provider for the data source. In this case we suppose we have a Datasource registered with the Jndi Name”ORACLEDS“. Since we are using WildFly as the container, we will be using by default the Hibernate persistence provider:

<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="<meta http-equiv="content-type" content="text/html; charset=utf-8">userDatabase">
        <jta-data-source>OracleDS</jta-data-source>
    </persistence-unit>
</persistence>

Writing a Session Bean facade

Now your Entity Bean is ready, we’ll concentrate on the Session Bean which will be our facade for our Entities.

A session bean facade can be used to encapsulate the complexity of interactions between the business objects participating in a workflow. The Session Facade manages the business objects, and provides a uniform coarse-grained service access layer to clients.

import java.io.Serializable;

import java.util.List;

import javax.ejb.*;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.jboss.annotation.ejb.Clustered;

@Stateless

public class HelloBean implements 
                          HelloBeanItf, Serializable {


@PersistenceContext(unitName="userDatabase")
private EntityManager em;


 public List<Note> findAll() {
  Query query = em.createQuery("Select h from Note h");
  return (List<Note>) query.getResultList();
 }

}

That’s all, besides the Stateless annotation we meet the EntityManager beast ! what is it ?

The Entity Manager is responsible for the entity objects and handling their persistence. The entity manager itself can handle multiple entity instances, the set of which is referred to as a Persistence context. For each record in the database, there will be only one instance of that entity bean stored inside the persistence context.

EntityManager itself comes from factories defined by the EntityManagerFactory interface.
The factory can then create server persistence units. In fact, different factories can reference the same persistence context. We are able to create an EntityManager from the factory via container-managed injection by @PersistenceContext. The parameter unitName contains the equivalent

<persistence-unit name=”userDatabase”> specified in the persistence.xml  file.

Finally, the last type of manipulation you are going to want to do is to find objects by queries. If you are familiar with the Hibernate way of using Query objects to query the database, this will come fairly easy to you.

public List<Note> findAll() {
  Query query = em.createQuery("Select h from Note h");
  return (List<Note>) query.getResultList();
}

In the previous code, we are finding all objects mapped as Note and returning them in a plain java.util.List collection. The language used to query the object is similar to SQL but it’s not regular SQL, it’s called Java Persistence Query Language. This language gives you a way to specify the semantics of queries in a portable way, independent of the particular database you’re using in an enterprise environment.

Packaging the EJB Entity application

An application which uses JPA requires to include the persistence.xml file under the resources/META-INF folder of your project. See as an example the following project tree of an application which uses EJB and JPA:

src
└── main
    ├── java
    │   └── com
    │       └── mastertheboss
    │           ├── ejb
    │           │   └── ServiceBean.java
    │           ├── model
    │           │   └── SimpleProperty.java
    │           └── rest
    │               ├── RestActivator.java
    │               └── RestService.java
    ├── resources
    │   └── META-INF
    │       └── persistence.xml
    └── webapp
        ├── index.html
        └── WEB-INF
            └── beans.xml

The recommended way to build your JPA application is to include the jakarta.jakartaee-api dependency within your pom.xml. For example, for Jakarta EE 8 applications:

<dependency>
   <groupId>jakarta.platform</groupId>
   <artifactId>jakarta.jakartaee-api</artifactId>
   <version>8.0.0</version>
   <scope>provided</scope>
</dependency>

Let’s improve our example: how to insert an object ?

quite simple, create the Object as a POJO and pass it to the Entity Manager which will care about persisting it !

Add this to your SLSB:

public void newNote(Note note) {
try {
  em.persist(note);
}
catch (Exception e) {
  e.printStackTrace();
}
}

Then in your Client:

Note newnote = new Note();
newnote.setActor("berth");
newnote.setAttachment("text attached");
newnote.setText("full text");

ejb.newNote(newnote);

Ok but what about deleting an Object ?

Deleting an Object (and therefore a row) from your SLSB requires finding it first and then calling the remove method on the Entity Manager.

public void deleteNote(long noteId) {
  Note note = em.find(Note.class, noteId);
  em.remove(note);
}

Ok but what about updating an Object ?

If you have understood how the EM works you shouldn’t even ask it! anyway it works the same as for Deleting an Object: find it first and change the property you like.

public void deleteNote(long noteId) {
  Note note = em.find(Note.class, noteId);
  note.setText("update the text please!");
}

Conclusion
In this article we’ve seen how to create a simple Entity Bean which can be deployed to WildFly application in a matter of minutes.

If you want to download a basic JPA application for WildFly, check this example:

https://github.com/fmarchioni/mastertheboss/tree/master/javaee/jpa-basic

How to access Hibernate Session in JPA applications?

In order to access Hibernate objects from a JPA application you can use the unwrap method available in the EntityManager and EntityManager Factory class:

EntityManager.<T>unwrap(Class<T>)
EntityManagerFactory.<T>unwrap(Class<T>)

This method can be used to gain access of JPA-vendor-specific classes. For example, here is how you can retrieve Hibernate’s Session and SessionFactory:

Session session = em.unwrap(Session.class);
SessionFactory sessionFactory = em.getEntityManagerFactory().unwrap(SessionFactory.class);

Please note: this method is available since JPA 2.0

JBoss AS 5

If you are running an older application server version (JBoss AS 5), you can get access to the current underlying Hibernate Session by typecasting your reference to EntityManager.:

       @PersistenceContext EntityManager entityManager;
       public void someMethod();
       {
         org.jboss.ejb3.entity.HibernateSession hs = (HibernateSession)entityManager;
         org.hibernate.Session session = hs.getHibernateSession();
       }

You can also get access to the current underlying Hibernate Query by typecasting your reference to a org.hibernate.ejb.QueryImpl.

       @PersistenceContext EntityManager entityManager;
       public void someMethod();
       {
         javax.persistence.Query query = entityManager.createQuery(...);
         org.hiberante.ejb.QueryImpl hs = (QueryImpl)query;
         org.hibernate.Query hbQuery = hs.getHibernateQuery();
       }

How to use native Queries in JPA ?

Native Queries are typically used to leverage some optimizations/features of your database which are not available through HQL/JPQL. Consider the following example:

@Stateless
public class ServiceBean  {
  private static final String QUERY =
    "SELECT emp_id, name, dept_id, address_id from Employee " +
    "START WITH manager_id = ? " +
    "CONNECT BY PRIOR emp_id = manager_id";
  @PersistenceContext(unitName = "EmployeeService")
  EntityManager em;
}
public List findEmployeesReportingTo(int managerId) {
    return em.createNativeQuery(QUERY, Employee.class)
      .setParameter(1, managerId)
      .getResultList();

The above SQL statement leverages a feature of Oracle DB (Hierarchical queries) using a clause:

... PRIOR expr = expr

To use the same feature in JPA, we can use the createNativeQuery method of the EntityManager interface.

The query engine uses the object-relational mapping of the entity to figure out which result column aliases map to which entity properties. As each row is processed, the query engine instantiates a new entity instance and sets the available data into it.

You can also define a Native Query as @NamedNativeQuery annotation. This annotation may be
placed on any entity and defines the name of the query as well as the query text. Like JP QL named
queries, the name of the query must be unique within the persistence unit. If the result type is an entity,
the resultClass element may be used to indicate the entity class. If the result requires a SQL mapping,
the resultSetMapping element may be used to specify the mapping name.

@NamedNativeQuery(
name="orgStructureReportingTo",
query="SELECT emp_id, name, salary, manager_id FROM employee " +
"START WITH manager_id = ? " +
"CONNECT BY PRIOR emp_id = manager_id",
resultClass=Employee.class
)

Also please note that the createNamedQuery() can return a TypedQuery whereas the createNativeQuery() method returns an untyped Query.

What about if your query returns more than one Entity ? You have to use the @SqlResultSetMapping
which will be passed to the method instead of the Entity:

At first we define the mapping:

@SqlResultSetMapping(name = "MyMapping",
entities = @EntityResult(entityClass = sample.Person.User.class))

then we can specify the mapping in the Query as follows:

Query q = em.createNativeQuery("SELECT p1.last_name, t1.title_name, t2.title_name
FROM person p1 INNER JOIN title t1 ON p1.title_1 = t1.title_abbrev,
     person p2 INNER JOIN title t2 ON p2.title_2 = t2.title_abbrev",
sample.Person.User.class);
return q.getResultList();

How to use an env variable in your persistence.xml ?

In this short tutorial we will show how to use variables in your persistence.xml so that you can dynamically specify the data source which is used by our application.

In WildFly the simplest and most elegant way to do that is enabling the property replacement in the ee subsystem, as in the following example:

<subsystem xmlns="urn:jboss:domain:ee:4.0">
      <spec-descriptor-property-replacement>true</spec-descriptor-property-replacement>
      <jboss-descriptor-property-replacement>true</jboss-descriptor-property-replacement> 
. . .
</subsystem>

Now you can use the BeanShell expression with the env prefix to reference environment variables. For example:

<property name="javax.persistence.jdbc.url" value="jdbc:mysql://${env.MYSQL_DB_HOST}:${env.MYSQL_DB_PORT}/mydbname"/> 
<property name="javax.persistence.jdbc.user" value="${env.MYSQL_DB_USERNAME}"/> 
<property name="javax.persistence.jdbc.password" value="${env.MYSQL_DB_PASSWORD}"/>

This strategy is particularly useful in cloud environment such as Openshift, where you can pass environment variables to your Applications, in order to customize them.

Earlier versions of JBoss AS

In earlier versions of JBoss AS (such as JBoss EAP 7) the approach was a bit different: you needed to wrap the dynamic part as variable using the ${variable} syntax. Later on you can specify the value for the variable using the -D option.

Let’s take as sample the persistence.xml which is part of the Kitchensink quickstarts.

Here is it, using the ${myds} variable instead of the “java:jboss/datasources/KitchensinkQuickstartDS”:

<persistence version="2.0"
   xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
        <a href="http://java.sun.com/xml/ns/persistence">http://java.sun.com/xml/ns/persistence</a>
        <a href="http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd</a>">
   <persistence-unit name="primary">
      <jta-data-source>${myds}</jta-data-source>
      <properties>
         <!-- Properties for Hibernate -->
         <property name="hibernate.hbm2ddl.auto" value="create-drop" />
         <property name="hibernate.show_sql" value="false" />
      </properties>
   </persistence-unit>
</persistence>

That’s all. Now start the application server with:

standalone.bat -Dmyds=java:jboss/datasources/KitchensinkQuickstartDS

Or (if you are using JBoss AS 4-5-6):

run.bat -Dmyds=java:jboss/datasources/KitchensinkQuickstartDS