EJB - Persistance

EJB 3.0, bean entité utilisé dans EJB 2.0 est largement remplacé par un mécanisme de persistance. Désormais, le bean entité est un simple POJO ayant un mappage avec une table.

Voici les principaux acteurs de l'API de persistance -

  • Entity- Un objet persistant représentant l'enregistrement du magasin de données. Il est bon d'être sérialisable.

  • EntityManager- Interface de persistance pour effectuer des opérations de données comme ajouter / supprimer / mettre à jour / trouver sur un objet persistant (entité). Cela aide également à exécuter des requêtes à l'aide deQuery interface.

  • Persistence unit (persistence.xml) - L'unité de persistance décrit les propriétés du mécanisme de persistance.

  • Data Source (*ds.xml)- La source de données décrit les propriétés liées au magasin de données telles que l'URL de connexion. nom d'utilisateur, mot de passe, etc.

Pour démontrer le mécanisme de persistance EJB, nous devons effectuer les tâches suivantes -

  • Step 1 - Créer une table dans la base de données.

  • Step 2 - Créer la classe Entity correspondant à la table.

  • Step 3 - Créer une source de données et une unité de persistance.

  • Step 4 - Créez un EJB sans état ayant une instance EntityManager.

  • Step 5- Mettre à jour EJB sans état. Ajoutez des méthodes pour ajouter des enregistrements et obtenir des enregistrements de la base de données via le gestionnaire d'entités.

  • Step 6 - Un client d'application basé sur une console accédera à l'EJB sans état pour conserver les données dans la base de données.

Créer une table

Créer une table books dans la base de données par défaut postgres.

CREATE TABLE books (
   id     integer PRIMARY KEY,
   name   varchar(50)
);

Créer une classe d'entité

//mark it entity using Entity annotation 
//map table name using Table annotation
@Entity
@Table(name="books")
public class Book implements Serializable{
    
   private int id;
   private String name;

   public Book() {        
   }

   //mark id as primary key with autogenerated value
   //map database column id with id field
   @Id
   @GeneratedValue(strategy= GenerationType.IDENTITY)
   @Column(name="id")
   public int getId() {
      return id;
   }
   ...
}

Créer une source de données et une unité de persistance

DataSource (jboss-ds.xml)

<?xml version = "1.0" encoding = "UTF-8"?>
<datasources>
   <local-tx-datasource>
      <jndi-name>PostgresDS</jndi-name>
      <connection-url>jdbc:postgresql://localhost:5432/postgres</connection-url>
      <driver-class>org.postgresql.driver</driver-class>
      <user-name>sa</user-name>
      <password>sa</password>
      <min-pool-size>5</min-pool-size>
      <max-pool-size>20</max-pool-size>
      <idle-timeout-minutes>5</idle-timeout-minutes>
   </local-tx-datasource>
</datasources>

Unité de persistance (persistence.xml)

<persistence version = "1.0" 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">

   <persistence-unit name = "EjbComponentPU" transaction-type = "JTA">
      <jta-data-source>java:/PostgresDS</jta-data-source>
      <exclude-unlisted-classes>false</exclude-unlisted-classes>
      <properties/>
   </persistence-unit>
   
   <persistence-unit name = "EjbComponentPU2" transaction-type = "JTA">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>java:/PostgresDS</jta-data-source>
      <exclude-unlisted-classes>false</exclude-unlisted-classes>
	  
      <properties>
         <property name="hibernate.hbm2ddl.auto" value="update"/>
      </properties>
   </persistence-unit>
   
</persistence>

Créer un EJB sans état avec une instance EntityManager

@Stateless
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
	
   //pass persistence unit to entityManager.
   @PersistenceContext(unitName="EjbComponentPU")
   private EntityManager entityManager;         

   public void addBook(Book book) {
      entityManager.persist(book);
   }    

   public List<Book> getBooks() {        
      return entityManager.createQuery("From Books").getResultList();
   }
   ...
}

Après avoir construit le module EJB, nous avons besoin d'un client pour accéder au bean sans état, que nous allons créer dans la section suivante.

Exemple d'application

Créons une application de test EJB pour tester le mécanisme de persistance des EJB.

Étape La description
1

Créez un projet avec un nom EjbComponent sous un package com.tutorialspoint.entity comme expliqué dans le chapitre EJB - Créer une application . Vous pouvez également utiliser le projet créé dans le chapitre EJB - Créer une application en tant que tel pour ce chapitre pour comprendre les concepts de persistance des EJB.

2

Créez Book.java sous le package com.tutorialspoint.entity et modifiez-le comme indiqué ci-dessous.

3

Créez LibraryPersistentBean.java et LibraryPersistentBeanRemote comme expliqué dans les chapitres EJB - Créer une application et modifiez-les comme indiqué ci-dessous.

4

Créez jboss-ds.xml dansEjbComponent > setup dossier et persistence.xml dansEjbComponent > src > conf dossier. Ces dossiers peuvent être vus dans l'onglet Fichiers de Netbeans. Modifiez ces fichiers comme indiqué ci-dessus.

5

Nettoyez et créez l'application pour vous assurer que la logique métier fonctionne conformément aux exigences.

6

Enfin, déployez l'application sous forme de fichier jar sur JBoss Application Server. Le serveur d'applications JBoss démarrera automatiquement s'il n'est pas encore démarré.

sept

Créez maintenant le client EJB, une application basée sur la console de la même manière que celle expliquée dans le chapitre EJB - Créer une application sous la rubriqueCreate Client to access EJB. Modifiez-le comme indiqué ci-dessous.

EJBComponent (module EJB)

Book.java

package com.tutorialspoint.entity;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="books")
public class Book implements Serializable{
    
   private int id;
   private String name;

   public Book() {        
   }

   @Id
   @GeneratedValue(strategy= GenerationType.IDENTITY)
   @Column(name="id")
   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;
   }    
}

LibraryPersistentBeanRemote.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;
import javax.ejb.Remote;

@Remote
public interface LibraryPersistentBeanRemote {

   void addBook(Book bookName);

   List<Book> getBooks();
    
}

LibraryPersistentBean.java

package com.tutorialspoint.stateless;

import com.tutorialspoint.entity.Book;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {
    
   public LibraryPersistentBean() {
   }

   @PersistenceContext(unitName="EjbComponentPU")
   private EntityManager entityManager;         

   public void addBook(Book book) {
      entityManager.persist(book);
   }    

   public List<Book> getBooks() {
      return entityManager.createQuery("From Book").getResultList();
   }
}
  • Dès que vous déployez le projet EjbComponent sur JBOSS, notez le journal jboss.

  • JBoss a créé automatiquement une entrée JNDI pour notre bean session - LibraryPersistentBean/remote.

  • Nous utiliserons cette chaîne de recherche pour obtenir un objet métier distant de type - com.tutorialspoint.stateless.LibraryPersistentBeanRemote

Sortie du journal du serveur d'applications JBoss

...
16:30:01,401 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
   LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
   LibraryPersistentBean/remote-com.tutorialspoint.stateless.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibraryPersistentBeanRemote,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.stateless.LibraryPersistentBeanRemote ejbName: LibraryPersistentBean
16:30:02,731 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

   LibraryPersistentBean/remote - EJB3.x Default Remote Business Interface
   LibraryPersistentBean/remote-com.tutorialspoint.stateless.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
...

EJBTester (client EJB)

jndi.properties

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost
  • Ces propriétés sont utilisées pour initialiser l'objet InitialContext du service de nommage java.

  • L'objet InitialContext sera utilisé pour rechercher un bean session sans état.

EJBTester.java

package com.tutorialspoint.test;
   
import com.tutorialspoint.stateless.LibraryPersistentBeanRemote;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class EJBTester {

   BufferedReader brConsoleReader = null; 
   Properties props;
   InitialContext ctx;
   {
      props = new Properties();
      try {
         props.load(new FileInputStream("jndi.properties"));
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      try {
         ctx = new InitialContext(props);            
      } catch (NamingException ex) {
         ex.printStackTrace();
      }
      brConsoleReader = 
      new BufferedReader(new InputStreamReader(System.in));
   }
   
   public static void main(String[] args) {

      EJBTester ejbTester = new EJBTester();

      ejbTester.testEntityEjb();
   }
   
   private void showGUI() {
      System.out.println("**********************");
      System.out.println("Welcome to Book Store");
      System.out.println("**********************");
      System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
   }
   
   private void testEntityEjb() {

      try {
         int choice = 1; 

         LibraryPersistentBeanRemote libraryBean =
         LibraryPersistentBeanRemote)ctx.lookup("LibraryPersistentBean/remote");

         while (choice != 2) {
            String bookName;
            showGUI();
            String strChoice = brConsoleReader.readLine();
            choice = Integer.parseInt(strChoice);
            if (choice == 1) {
               System.out.print("Enter book name: ");
               bookName = brConsoleReader.readLine();
               Book book = new Book();
               book.setName(bookName);
               libraryBean.addBook(book);          
            } else if (choice == 2) {
               break;
            }
         }

         List<Book> booksList = libraryBean.getBooks();

         System.out.println("Book(s) entered so far: " + booksList.size());
         int i = 0;
         for (Book book:booksList) {
            System.out.println((i+1)+". " + book.getName());
            i++;
         }           
      } catch (Exception e) {
         System.out.println(e.getMessage());
         e.printStackTrace();
      }finally {
         try {
            if(brConsoleReader !=null) {
               brConsoleReader.close();
            }
         } catch (IOException ex) {
            System.out.println(ex.getMessage());
         }
      }
   }
}

EJBTester effectue les tâches suivantes.

  • Chargez les propriétés de jndi.properties et initialisez l'objet InitialContext.

  • Dans la méthode testStatefulEjb (), la recherche jndi est effectuée avec le nom - "LibraryStatefulSessionBean / remote" pour obtenir l'objet métier distant (stateful ejb).

  • Ensuite, l'utilisateur voit une interface utilisateur de magasin de bibliothèque et il / elle est invité à entrer le choix.

  • Si l'utilisateur entre 1, le système demande le nom du livre et enregistre le livre en utilisant la méthode addBook () du bean session sans état. Session Bean persiste le livre dans la base de données via un appel EntityManager.

  • Si l'utilisateur entre 2, le système récupère les livres à l'aide de la méthode getBooks () du bean session avec état et se ferme.

  • Ensuite, une autre recherche jndi est effectuée avec le nom - "LibraryStatelessSessionBean / remote" pour obtenir à nouveau l'objet métier distant (EJB sans état) et la liste des livres est effectuée.

Exécuter le client pour accéder à EJB

Recherchez EJBTester.java dans l'explorateur de projet. Faites un clic droit sur la classe EJBTester et sélectionnezrun file.

Vérifiez la sortie suivante dans la console Netbeans -

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: Learn Java
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 1
1. learn java
BUILD SUCCESSFUL (total time: 15 seconds)

Exécutez à nouveau le client pour accéder à EJB

Redémarrez le JBoss avant d'accéder à l'EJB.

Recherchez EJBTester.java dans l'explorateur de projet. Faites un clic droit sur la classe EJBTester et sélectionnezrun file.

Vérifiez la sortie suivante dans la console Netbeans.

run:
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 1
Enter book name: Learn Spring
**********************
Welcome to Book Store
**********************
Options 
1. Add Book
2. Exit 
Enter Choice: 2
Book(s) entered so far: 2
1. learn java
2. Learn Spring
BUILD SUCCESSFUL (total time: 15 seconds)

La sortie montrée ci-dessus indique que les livres sont stockés dans un stockage persistant et sont extraits de la base de données.