Учебники

EJB — настойчивость

EJB 3.0, объектный компонент, используемый в EJB 2.0, в значительной степени заменен механизмом персистентности. Теперь объектный бин — это простой POJO, имеющий отображение с таблицей.

Ниже приведены ключевые действующие лица в постоянном API.

  • Entity — постоянный объект, представляющий запись хранилища данных. Хорошо быть сериализуемым.

  • EntityManager — Персистентный интерфейс для выполнения операций с данными, таких как добавление / удаление / обновление / поиск над постоянным объектом (сущностью). Это также помогает выполнять запросы, используя интерфейс запросов .

  • Модуль сохраняемости (persistence.xml) — модуль сохраняемости описывает свойства механизма сохранения.

  • Источник данных (* ds.xml) — Источник данных описывает свойства, связанные с хранилищем данных, такие как URL-адрес соединения. имя пользователя, пароль и т. д.

Entity — постоянный объект, представляющий запись хранилища данных. Хорошо быть сериализуемым.

EntityManager — Персистентный интерфейс для выполнения операций с данными, таких как добавление / удаление / обновление / поиск над постоянным объектом (сущностью). Это также помогает выполнять запросы, используя интерфейс запросов .

Модуль сохраняемости (persistence.xml) — модуль сохраняемости описывает свойства механизма сохранения.

Источник данных (* ds.xml) — Источник данных описывает свойства, связанные с хранилищем данных, такие как URL-адрес соединения. имя пользователя, пароль и т. д.

Чтобы продемонстрировать механизм персистентности EJB, нам нужно выполнить следующие задачи:

  • Шаг 1 — Создать таблицу в базе данных.

  • Шаг 2 — Создайте класс Entity, соответствующий таблице.

  • Шаг 3 — Создание источника данных и модуля персистентности.

  • Шаг 4 — Создайте EJB без состояния, имеющий экземпляр EntityManager.

  • Шаг 5 — Обновите EJB без сохранения состояния. Добавьте методы для добавления записей и получения записей из базы данных через менеджер сущностей.

  • Шаг 6 — Клиент консольного приложения получит доступ к EJB без сохранения состояния для сохранения данных в базе данных.

Шаг 1 — Создать таблицу в базе данных.

Шаг 2 — Создайте класс Entity, соответствующий таблице.

Шаг 3 — Создание источника данных и модуля персистентности.

Шаг 4 — Создайте EJB без состояния, имеющий экземпляр EntityManager.

Шаг 5 — Обновите EJB без сохранения состояния. Добавьте методы для добавления записей и получения записей из базы данных через менеджер сущностей.

Шаг 6 — Клиент консольного приложения получит доступ к EJB без сохранения состояния для сохранения данных в базе данных.

Создать таблицу

Создать таблицу книг по умолчанию в базе данных postgres .

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

Создать класс сущности

//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;
   }
   ...
}

Создать источник данных и блок персистентности

Источник данных (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>

Персистентный блок (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>

Создайте EJB без состояния, имеющий экземпляр 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();
   }
   ...
}

После создания модуля EJB нам нужен клиент для доступа к bean-компоненту без сохранения состояния, который мы собираемся создать в следующем разделе.

Пример приложения

Давайте создадим тестовое EJB-приложение для тестирования механизма персистентности EJB.

шаг Описание
1

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.entity, как описано в главе EJB — Создание приложения . Вы также можете использовать проект, созданный в главе EJB — Создание приложения как таковой, для понимания концепций персистентности EJB.

2

Создайте Book.java в пакете com.tutorialspoint.entity и измените его, как показано ниже.

3

Создайте LibraryPersistentBean.java и LibraryPersistentBeanRemote, как описано в главах EJB — Создание приложения, и измените их, как показано ниже.

4

Создайте jboss-ds.xml в EjbComponent> установочной папке и persistence.xml в EjbComponent> src> conf . Эти папки можно увидеть на вкладке файлов в Netbeans. Измените эти файлы, как показано выше.

5

Очистите и создайте приложение, чтобы убедиться, что бизнес-логика работает в соответствии с требованиями.

6

Наконец, разверните приложение в виде файла JAR на сервере приложений JBoss. Сервер приложений JBoss запустится автоматически, если он еще не запущен.

7

Теперь создайте EJB-клиент, консольное приложение, аналогично тому, как описано в главе EJB — Создание приложения в разделе « Создание клиента для доступа к EJB» . Измените его, как показано ниже.

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.entity, как описано в главе EJB — Создание приложения . Вы также можете использовать проект, созданный в главе EJB — Создание приложения как таковой, для понимания концепций персистентности EJB.

Создайте Book.java в пакете com.tutorialspoint.entity и измените его, как показано ниже.

Создайте LibraryPersistentBean.java и LibraryPersistentBeanRemote, как описано в главах EJB — Создание приложения, и измените их, как показано ниже.

Создайте jboss-ds.xml в EjbComponent> установочной папке и persistence.xml в EjbComponent> src> conf . Эти папки можно увидеть на вкладке файлов в Netbeans. Измените эти файлы, как показано выше.

Очистите и создайте приложение, чтобы убедиться, что бизнес-логика работает в соответствии с требованиями.

Наконец, разверните приложение в виде файла JAR на сервере приложений JBoss. Сервер приложений JBoss запустится автоматически, если он еще не запущен.

Теперь создайте EJB-клиент, консольное приложение, аналогично тому, как описано в главе EJB — Создание приложения в разделе « Создание клиента для доступа к EJB» . Измените его, как показано ниже.

EJBComponent (модуль 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();
   }
}
  • Как только вы развернете проект EjbComponent в JBOSS, обратите внимание на журнал jboss.

  • JBoss автоматически создал запись JNDI для нашего сессионного компонента — LibraryPersistentBean / remote .

  • Мы будем использовать эту строку поиска для получения удаленного бизнес-объекта типа — com.tutorialspoint.stateless.LibraryPersistentBeanRemote

Как только вы развернете проект EjbComponent в JBOSS, обратите внимание на журнал jboss.

JBoss автоматически создал запись JNDI для нашего сессионного компонента — LibraryPersistentBean / remote .

Мы будем использовать эту строку поиска для получения удаленного бизнес-объекта типа — com.tutorialspoint.stateless.LibraryPersistentBeanRemote

Вывод журнала сервера приложений 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 (клиент 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
  • Эти свойства используются для инициализации объекта InitialContext сервиса именования java.

  • Объект InitialContext будет использоваться для поиска сессионного компонента без сохранения состояния.

Эти свойства используются для инициализации объекта InitialContext сервиса именования java.

Объект InitialContext будет использоваться для поиска сессионного компонента без сохранения состояния.

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 выполняет следующие задачи.

  • Загрузите свойства из jndi.properties и инициализируйте объект InitialContext.

  • В методе testStatefulEjb () поиск jndi выполняется с именем — «LibraryStatefulSessionBean / remote» для получения удаленного бизнес-объекта (stateful ejb).

  • Затем пользователю показывается пользовательский интерфейс магазина библиотеки, и ему / ей предлагается ввести выбор.

  • Если пользователь вводит 1, система запрашивает имя книги и сохраняет книгу, используя метод addBook () сессионного компонента без сохранения состояния. Сессионный компонент сохраняет книгу в базе данных с помощью вызова EntityManager.

  • Если пользователь вводит 2, система получает книги, используя метод getBooks () сессионного компонента с состоянием, и завершает работу.

  • Затем выполняется другой поиск jndi с именем — «LibraryStatelessSessionBean / remote» для повторного получения удаленного бизнес-объекта (EJB без сохранения состояния) и составления списка книг.

Загрузите свойства из jndi.properties и инициализируйте объект InitialContext.

В методе testStatefulEjb () поиск jndi выполняется с именем — «LibraryStatefulSessionBean / remote» для получения удаленного бизнес-объекта (stateful ejb).

Затем пользователю показывается пользовательский интерфейс магазина библиотеки, и ему / ей предлагается ввести выбор.

Если пользователь вводит 1, система запрашивает имя книги и сохраняет книгу, используя метод addBook () сессионного компонента без сохранения состояния. Сессионный компонент сохраняет книгу в базе данных с помощью вызова EntityManager.

Если пользователь вводит 2, система получает книги, используя метод getBooks () сессионного компонента с состоянием, и завершает работу.

Затем выполняется другой поиск jndi с именем — «LibraryStatelessSessionBean / remote» для повторного получения удаленного бизнес-объекта (EJB без сохранения состояния) и составления списка книг.

Запустите клиент для доступа к EJB

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберите файл запуска .

Проверьте следующий вывод в консоли 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)

Снова запустите клиент для доступа к EJB

Перезапустите JBoss, прежде чем получить доступ к EJB.

Найдите EJBTester.java в проводнике проекта. Щелкните правой кнопкой мыши класс EJBTester и выберите файл запуска .

Проверьте следующий вывод в консоли 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)

Вывод, показанный выше, гласит, что книги хранятся в постоянном хранилище и извлекаются из базы данных.