Учебники

EJB — отношения сущностей

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

Ниже приведены соответствующие аннотации —

  • Один-к-одному — объекты имеют отношение один-к-одному. Например, пассажир может путешествовать по одному билету за раз.

  • Один-ко-многим — объекты имеют отношение один-ко-многим. Например, у отца может быть несколько детей.

  • Многие-к-одному — объекты имеют отношение многие-к-одному. Например, у нескольких детей есть мать-одиночка.

  • Многие ко многим — Объекты имеют отношение ко многим. Например, книга может иметь несколько авторов, а автор может написать несколько книг.

Один-к-одному — объекты имеют отношение один-к-одному. Например, пассажир может путешествовать по одному билету за раз.

Один-ко-многим — объекты имеют отношение один-ко-многим. Например, у отца может быть несколько детей.

Многие-к-одному — объекты имеют отношение многие-к-одному. Например, у нескольких детей есть мать-одиночка.

Многие ко многим — Объекты имеют отношение ко многим. Например, книга может иметь несколько авторов, а автор может написать несколько книг.

Мы продемонстрируем использование отображения ManyToMany здесь. Для представления отношений ManyToMany необходимы три следующие таблицы:

  • Книга — книжный стол, имеющий записи книг.

  • Автор — Автор таблицы, имеющий записи автора.

  • Book_Author — таблица «Автор книги», имеющая связь между вышеупомянутой таблицей «Книга» и «Автор».

Книга — книжный стол, имеющий записи книг.

Автор — Автор таблицы, имеющий записи автора.

Book_Author — таблица «Автор книги», имеющая связь между вышеупомянутой таблицей «Книга» и «Автор».

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

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

CREATE TABLE book (
   book_id     integer,   
   name   varchar(50)      
);

CREATE TABLE author (
   author_id   integer,
   name   varchar(50)      
);

CREATE TABLE book_author (
   book_id     integer,
   author_id   integer 
);

Создать классы сущностей

@Entity
@Table(name="author")
public class Author implements Serializable{
   private int id;
   private String name;
   ...   
}

@Entity
@Table(name="book")
public class Book implements Serializable{
   private int id;
   private String title;
   private Set<Author> authors;
   ...   
}

Используйте аннотацию ManyToMany в Book Entity.

@Entity
public class Book implements Serializable{
   ...
   @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}
      , fetch = FetchType.EAGER)
   @JoinTable(table = @Table(name = "book_author"),
      joinColumns = {@JoinColumn(name = "book_id")},
      inverseJoinColumns = {@JoinColumn(name = "author_id")})
   public Set<Author> getAuthors() {
      return authors;
   }
   ...
}

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

Давайте создадим тестовое EJB-приложение для тестирования объектов отношений сущностей в EJB 3.0.

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

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.entity, как описано в главе EJB — Создание приложения . Пожалуйста, используйте проект, созданный в главе EJB — Постоянство как таковой для этой главы, чтобы понять встроенные объекты в концепциях EJB.

2

Создайте Author.java в пакете com.tutorialspoint.entity, как описано в главе EJB — Создание приложения . Сохраните остальные файлы без изменений.

3

Создайте Book.java в пакете com.tutorialspoint.entity . Используйте EJB — главу Постоянство в качестве ссылки. Сохраните остальные файлы без изменений.

4

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

5

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

6

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

Создайте проект с именем EjbComponent в пакете com.tutorialspoint.entity, как описано в главе EJB — Создание приложения . Пожалуйста, используйте проект, созданный в главе EJB — Постоянство как таковой для этой главы, чтобы понять встроенные объекты в концепциях EJB.

Создайте Author.java в пакете com.tutorialspoint.entity, как описано в главе EJB — Создание приложения . Сохраните остальные файлы без изменений.

Создайте Book.java в пакете com.tutorialspoint.entity . Используйте EJB — главу Постоянство в качестве ссылки. Сохраните остальные файлы без изменений.

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

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

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

EJBComponent (модуль EJB)

Author.java

package com.tutorialspoint.entity;

import java.io.Serializable;

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

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

   public Author() {}

   public Author(int id, String name) {
      this.id = id;
      this.name = name;
   }
   
   @Id  
   @GeneratedValue(strategy= GenerationType.IDENTITY)
   @Column(name="author_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;
   }

   public String toString() {
      return id + "," + name;
   }    
}

Book.java

package com.tutorialspoint.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;

@Entity
@Table(name="book")
public class Book implements Serializable{

   private int id;
   private String name;
   private Set<Author> authors;

   public Book() {        
   }

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

   public void setAuthors(Set<Author> authors) {
      this.authors = authors;
   }    
   
   @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}
      , fetch = FetchType.EAGER)
   @JoinTable(table = @Table(name = "book_author"),
      joinColumns = {@JoinColumn(name = "book_id")},
      inverseJoinColumns = {@JoinColumn(name = "author_id")})
   public Set<Author> getAuthors() {
      return authors;
   }
}

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.interceptor.LibraryPersistentBeanRemote

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

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

Мы будем использовать эту строку поиска для получения удаленного бизнес-объекта типа — com.tutorialspoint.interceptor.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.interceptor.LibraryPersistentBeanRemote - EJB3.x Remote Business Interface
16:30:02,723 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibraryPersistentBean,service=EJB3
16:30:02,723 INFO  [EJBContainer] STARTED EJB: com.tutorialspoint.interceptor.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.interceptor.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.stateful.LibraryBeanRemote;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import java.util.*;

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.testEmbeddedObjects();
   }
   
   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 testEmbeddedObjects() {

      try {
         int choice = 1; 

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

         while (choice != 2) {
            String bookName;
            String authorName;
            
            showGUI();
            String strChoice = brConsoleReader.readLine();
            choice = Integer.parseInt(strChoice);
            if (choice == 1) {
               System.out.print("Enter book name: ");
               bookName = brConsoleReader.readLine();
               System.out.print("Enter author name: ");
               authorName = brConsoleReader.readLine();               
               Book book = new Book();
               book.setName(bookName);
               Author author = new Author();
               author.setName(authorName);
               Set<Author> authors = new HashSet<Author>();
               authors.add(author);
               book.setAuthors(authors);

               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());
            System.out.print("Author: ");
            Author[] authors = (Author[])books.getAuthors().toArray();
            for(int j=0;j<authors.length;j++) {
               System.out.println(authors[j]);
            }
            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.

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

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

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

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

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

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

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

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

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

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

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

Проверьте следующий вывод в консоли Netbeans.