| = JPA Hibernate |
| :index-group: JPA |
| :jbake-type: page |
| :jbake-status: published |
| |
| This example shows the persist, remove and creation a query in JPA Hibernate. |
| The Java Persistence API (JPA) is a Java specification for accessing, persisting, and managing data between Java objects / classes and a relational database. |
| |
| To exemplify the use of JPA, we will persist an Object (Movie) in the database. |
| |
| Links to the documentation have been added in key parts of the example for the case of doubts and as a way to encourage their reading for details. |
| |
| == Movie |
| |
| Here we have a class with some details. See the annotation |
| link:https://tomee.apache.org/tomee-9.0/javadoc/jakarta/persistence/Entity.html[@Entity] |
| above the declaration, with it we are saying that this class is an entity (a table in the database). We still have two more annotations above the attribute id, one of them is |
| link:https://tomee.apache.org/tomee-9.0/javadoc/jakarta/persistence/Id.html[@Id] |
| annotation, it indicates that this attribute is the identifier of the entity and the other annotation |
| link:https://tomee.apache.org/tomee-9.0/javadoc/jakarta/persistence/GeneratedValue.html[@GeneratedValue] |
| indicates that the unique identifier value generation of the entity will be managed by the persistence provider. |
| |
| [source,java] |
| ---- |
| package org.superbiz.injection.h5jpa; |
| |
| import jakarta.persistence.Entity; |
| import jakarta.persistence.GeneratedValue; |
| import jakarta.persistence.GenerationType; |
| import jakarta.persistence.Id; |
| |
| @Entity |
| public class Movie { |
| |
| @Id |
| @GeneratedValue(strategy = GenerationType.AUTO) |
| private long id; |
| |
| private String director; |
| private String title; |
| private int year; |
| |
| public Movie() { |
| } |
| |
| public Movie(String director, String title, int year) { |
| this.director = director; |
| this.title = title; |
| this.year = year; |
| } |
| |
| public String getDirector() { |
| return director; |
| } |
| |
| public void setDirector(String director) { |
| this.director = director; |
| } |
| |
| public String getTitle() { |
| return title; |
| } |
| |
| public void setTitle(String title) { |
| this.title = title; |
| } |
| |
| public int getYear() { |
| return year; |
| } |
| |
| public void setYear(int year) { |
| this.year = year; |
| } |
| |
| } |
| ---- |
| |
| == Movies |
| |
| Now we have two important things: |
| link:https://tomee.apache.org/tomee-8.0/javadoc/javax/persistence/PersistenceContext.html[@PersistenceContext] |
| annotation and the |
| link:https://tomee.apache.org/tomee-8.0/javadoc/javax/persistence/EntityManager.html[EntityManager] |
| declaration. |
| The |
| link:https://tomee.apache.org/tomee-8.0/javadoc/javax/persistence/EntityManager.html[EntityManager] |
| is the interface with the core methods of JPA like persist, remove, merge, find and others... |
| We annotate the |
| link:https://tomee.apache.org/tomee-8.0/javadoc/javax/persistence/EntityManager.html[EntityManager] |
| with |
| link:https://tomee.apache.org/tomee-8.0/javadoc/javax/persistence/PersistenceContext.html[@PersistenceContext], a persistence context is an entity management where every persistence context associated with a persistence unit, we will create a persistence.xml soon for this. |
| |
| [source,java] |
| ---- |
| package org.superbiz.injection.h5jpa; |
| |
| import jakarta.ejb.Stateful; |
| import jakarta.persistence.EntityManager; |
| import jakarta.persistence.PersistenceContext; |
| import jakarta.persistence.PersistenceContextType; |
| import jakarta.persistence.Query; |
| import java.util.List; |
| |
| @Stateful |
| public class Movies { |
| |
| @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED) |
| private EntityManager entityManager; |
| |
| public void addMovie(Movie movie) throws Exception { |
| entityManager.persist(movie); |
| } |
| |
| public void deleteMovie(Movie movie) throws Exception { |
| entityManager.remove(movie); |
| } |
| |
| public List<Movie> getMovies() throws Exception { |
| Query query = entityManager.createQuery("SELECT m from Movie as m"); |
| return query.getResultList(); |
| } |
| } |
| ---- |
| |
| == persistence.xml |
| |
| Here we define which database will persist our movies, and we perform other configurations such as: define a persistence-unit with the name movie-unit, followed by the definition of the JPA provider/implementation (in this case Hibernate) and we set some properties for hibernate. |
| Note, that we are using application composers in our test, so we do not need it in it's xml representation. |
| |
| [source,xml] |
| ---- |
| <persistence xmlns="https://jakarta.ee/xml/ns/persistence" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd" |
| version="3.0"> |
| <persistence-unit name="movie-unit"> |
| <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> |
| <jta-data-source>movieDatabase</jta-data-source> |
| <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source> |
| <properties> |
| <property name="hibernate.hbm2ddl.auto" value="create-drop"/> |
| <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/> |
| <property name="tomee.jpa.cdi" value="false"/> |
| </properties> |
| </persistence-unit> |
| </persistence> |
| ---- |
| |
| == MoviesTest |
| |
| Now we do a test, persisting three films, then we perform a search and finally we delete them. |
| |
| [source,java] |
| ---- |
| package org.superbiz.injection.h5jpa; |
| |
| import jakarta.inject.Inject; |
| import org.apache.openejb.jee.EjbJar; |
| import org.apache.openejb.jee.jpa.unit.PersistenceUnit; |
| import org.apache.openejb.junit.ApplicationComposer; |
| import org.apache.openejb.testing.Classes; |
| import org.apache.openejb.testing.Configuration; |
| import org.apache.openejb.testing.Module; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import java.util.List; |
| import java.util.Properties; |
| |
| import static org.junit.Assert.assertEquals; |
| |
| @RunWith(ApplicationComposer.class) |
| public class MoviesTest { |
| |
| @Inject |
| private Movies movies; |
| |
| @Module |
| public PersistenceUnit persistence() { |
| PersistenceUnit unit = new PersistenceUnit("movie-unit"); |
| unit.setJtaDataSource("movieDatabase"); |
| unit.setNonJtaDataSource("movieDatabaseUnmanaged"); |
| unit.getClazz().add(Movie.class.getName()); |
| unit.setProvider("org.hibernate.jpa.HibernatePersistenceProvider"); |
| unit.setProperty("hibernate.hbm2ddl.auto", "create-drop"); |
| unit.setProperty("tomee.jpa.cdi", "false"); |
| return unit; |
| } |
| |
| @Module |
| @Classes(cdi = true, value = Movies.class) |
| public EjbJar beans() { |
| EjbJar ejbJar = new EjbJar("movie-beans"); |
| return ejbJar; |
| } |
| |
| @Configuration |
| public Properties config() throws Exception { |
| Properties p = new Properties(); |
| p.put("movieDatabase", "new://Resource?type=DataSource"); |
| p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver"); |
| p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb"); |
| return p; |
| } |
| |
| @Test |
| public void test() throws Exception { |
| movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992)); |
| movies.addMovie(new Movie("Joel Coen", "Fargo", 1996)); |
| movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998)); |
| |
| List<Movie> list = movies.getMovies(); |
| assertEquals("List.size()", 3, list.size()); |
| |
| for (Movie movie : list) { |
| movies.deleteMovie(movie); |
| } |
| |
| assertEquals("Movies.getMovies()", 0, movies.getMovies().size()); |
| } |
| } |
| ---- |
| |
| == Running |
| |
| To run the example via maven: |
| |
| Access the project folder: |
| [source,bash] |
| ---- |
| cd jpa-hibernate |
| ---- |
| And execute: |
| [source,bash] |
| ---- |
| mvn clean install |
| ---- |
| |
| Which will generate output similar to the following: |
| |
| [source,console] |
| ---- |
| ------------------------------------------------------- |
| T E S T S |
| ------------------------------------------------------- |
| Running org.superbiz.injection.h5jpa.MoviesTest |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Created new singletonService org.apache.openejb.cdi.ThreadSingletonServiceImpl@176d53b2 |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Succeeded in installing singleton service |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Cannot find the configuration file [conf/openejb.xml]. Will attempt to create one for the beans deployed. |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Creating TransactionManager(id=Default Transaction Manager) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Creating SecurityService(id=Default Security Service) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Creating Resource(id=movieDatabase) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Configuring enterprise application: /home/zowallar/Dokumente/work/coding/tomee/examples/jpa-hibernate/MoviesTest |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Auto-deploying ejb Movies: EjbDeployment(deployment-id=Movies) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Auto-creating a container for bean org.superbiz.injection.h5jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Creating Container(id=Default Managed Container) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Using directory /tmp for stateful session passivation |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Creating Container(id=Default Stateful Container) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Using directory /tmp for stateful session passivation |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Configuring PersistenceUnit(name=movie-unit, provider=org.hibernate.jpa.HibernatePersistenceProvider) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource' for 'movie-unit'. |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Creating Resource(id=movieDatabaseNonJta) |
| März 24, 2022 9:34:39 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Adjusting PersistenceUnit movie-unit <non-jta-data-source> to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged' |
| März 24, 2022 9:34:40 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Enterprise application "/home/zowallar/Dokumente/work/coding/tomee/examples/jpa-hibernate/MoviesTest" loaded. |
| März 24, 2022 9:34:40 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Not creating another application classloader for MoviesTest |
| März 24, 2022 9:34:40 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Assembling app: /home/zowallar/Dokumente/work/coding/tomee/examples/jpa-hibernate/MoviesTest |
| März 24, 2022 9:34:40 VORM. org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation |
| INFO: HHH000204: Processing PersistenceUnitInfo [name: movie-unit] |
| März 24, 2022 9:34:40 VORM. org.hibernate.Version logVersion |
| INFO: HHH000412: Hibernate ORM core version 5.6.7.Final |
| März 24, 2022 9:34:40 VORM. org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit> |
| INFO: HCANN000001: Hibernate Commons Annotations {5.1.2.Final} |
| März 24, 2022 9:34:40 VORM. org.hibernate.dialect.Dialect <init> |
| INFO: HHH000400: Using dialect: org.hibernate.dialect.HSQLDialect |
| März 24, 2022 9:34:40 VORM. org.hibernate.resource.beans.spi.ManagedBeanRegistryInitiator resolveBeanContainer |
| INFO: HHH10005002: No explicit CDI BeanManager reference was passed to Hibernate, but CDI is available on the Hibernate ClassLoader. |
| März 24, 2022 9:34:40 VORM. org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService |
| INFO: HHH000490: Using JtaPlatform implementation: [org.apache.openejb.hibernate.OpenEJBJtaPlatform2] |
| März 24, 2022 9:34:40 VORM. org.hibernate.validator.internal.util.Version <clinit> |
| INFO: HV000001: Hibernate Validator 7.0.4.Final |
| März 24, 2022 9:34:41 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: PersistenceUnit(name=movie-unit, provider=org.hibernate.jpa.HibernatePersistenceProvider) - provider time 1292ms |
| WARNING: An illegal reflective access operation has occurred |
| WARNING: Illegal reflective access by org.apache.openejb.util.proxy.ClassDefiner (file:/home/zowallar/.m2/repository/org/apache/tomee/openejb-core/9.0.0-M9-SNAPSHOT/openejb-core-9.0.0-M9-SNAPSHOT.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) |
| WARNING: Please consider reporting this to the maintainers of org.apache.openejb.util.proxy.ClassDefiner |
| WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations |
| WARNING: All illegal access operations will be denied in a future release |
| März 24, 2022 9:34:41 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Jndi(name=MoviesLocalBean) --> Ejb(deployment-id=Movies) |
| März 24, 2022 9:34:41 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Jndi(name=global/MoviesTest/movie-beans/Movies!org.superbiz.injection.h5jpa.Movies) --> Ejb(deployment-id=Movies) |
| März 24, 2022 9:34:41 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Jndi(name=global/MoviesTest/movie-beans/Movies) --> Ejb(deployment-id=Movies) |
| März 24, 2022 9:34:41 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Existing thread singleton service in SystemInstance(): org.apache.openejb.cdi.ThreadSingletonServiceImpl@176d53b2 |
| März 24, 2022 9:34:41 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: OpenWebBeans Container is starting... |
| März 24, 2022 9:34:41 VORM. org.apache.webbeans.plugins.PluginLoader startUp |
| INFORMATION: Adding OpenWebBeansPlugin : [CdiPlugin] |
| März 24, 2022 9:34:42 VORM. org.apache.webbeans.config.BeansDeployer validateInjectionPoints |
| INFORMATION: All injection points were validated successfully. |
| März 24, 2022 9:34:42 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: OpenWebBeans Container has started, it took 665 ms. |
| März 24, 2022 9:34:42 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) |
| März 24, 2022 9:34:42 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) |
| März 24, 2022 9:34:42 VORM. org.apache.batchee.container.services.ServicesManager init |
| WARNUNG: You didn't specify org.apache.batchee.jmx.application and JMX is already registered, skipping |
| März 24, 2022 9:34:42 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Deployed Application(path=/home/zowallar/Dokumente/work/coding/tomee/examples/jpa-hibernate/MoviesTest) |
| März 24, 2022 9:34:42 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Undeploying app: /home/zowallar/Dokumente/work/coding/tomee/examples/jpa-hibernate/MoviesTest |
| März 24, 2022 9:34:42 VORM. org.hibernate.tool.schema.internal.SchemaDropperImpl$DelayedDropActionImpl perform |
| INFO: HHH000477: Starting delayed evictData of schema as part of SessionFactory shut-down' |
| März 24, 2022 9:34:42 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Closing DataSource: movieDatabase |
| März 24, 2022 9:34:42 VORM. org.apache.openejb.util.LogStreamAsync run |
| INFORMATION: Closing DataSource: movieDatabaseNonJta |
| Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.567 sec |
| |
| Results : |
| |
| Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 |
| ---- |