EJB - Relaciones entre entidades
EJB 3.0 ofrece la opción de definir relaciones / asignaciones de entidades de base de datos como relaciones uno a uno, uno a muchos, muchos a uno y muchos a muchos.
A continuación se muestran las anotaciones relevantes:
One-to-One- Los objetos tienen una relación de uno a uno. Por ejemplo, un pasajero puede viajar usando un solo boleto a la vez.
One-to-Many- Los objetos tienen una relación de uno a varios. Por ejemplo, un padre puede tener varios hijos.
Many-to-One- Los objetos tienen una relación de varios a uno. Por ejemplo, varios niños que tienen una madre soltera.
Many-to-Many- Los objetos tienen una relación de varios a varios. Por ejemplo, un libro puede tener varios autores y un autor puede escribir varios libros.
Demostraremos el uso del mapeo ManyToMany aquí. Para representar la relación ManyToMany, se requieren tres tablas siguientes:
Book - Mesa de libros, teniendo registros de libros.
Author - Tabla de autor, teniendo registros de autor.
Book_Author - Tabla de autor del libro, con la vinculación de la tabla de libro y autor antes mencionada.
Crear tablas
Crea una tabla book author, book_author en la base de datos predeterminada 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
);
Crear clases de entidad
@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;
...
}
Utilice la anotación ManyToMany en la entidad del libro.
@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;
}
...
}
Aplicación de ejemplo
Creemos una aplicación EJB de prueba para probar objetos de relaciones entre entidades en EJB 3.0.
Paso | Descripción |
---|---|
1 | Cree un proyecto con un nombre EjbComponent en un paquete com.tutorialspoint.entity como se explica en el capítulo EJB - Crear aplicación . Utilice el proyecto creado en el capítulo EJB - Persistencia como tal para este capítulo para comprender los objetos incrustados en los conceptos de EJB. |
2 | Cree Author.java en el paquete com.tutorialspoint.entity como se explica en el capítulo EJB - Crear aplicación . Mantenga el resto de los archivos sin cambios. |
3 | Cree Book.java en el paquete com.tutorialspoint.entity . Utilice el capítulo EJB - Persistencia como referencia. Mantenga el resto de los archivos sin cambios. |
4 | Limpie y compile la aplicación para asegurarse de que la lógica empresarial funcione según los requisitos. |
5 | Finalmente, implemente la aplicación en forma de archivo jar en JBoss Application Server. El servidor de aplicaciones JBoss se iniciará automáticamente si aún no se ha iniciado. |
6 | Ahora cree el cliente EJB, una aplicación basada en consola de la misma manera que se explica en el capítulo EJB - Crear aplicación en el temaCreate Client to access EJB. |
EJBComponent (módulo EJB)
Autor.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();
}
}
Tan pronto como implemente el proyecto EjbComponent en JBOSS, observe el registro de jboss.
JBoss ha creado automáticamente una entrada JNDI para nuestro bean de sesión - LibraryPersistentBean/remote.
Usaremos esta cadena de búsqueda para obtener un objeto comercial remoto de tipo: com.tutorialspoint.interceptor.LibraryPersistentBeanRemote
Salida de registro del servidor de aplicaciones 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 (cliente 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
Estas propiedades se utilizan para inicializar el objeto InitialContext del servicio de nombres de Java.
El objeto InitialContext se utilizará para buscar un bean de sesión sin estado.
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 realiza las siguientes tareas:
Cargue las propiedades de jndi.properties e inicialice el objeto InitialContext.
En el método testInterceptedEjb (), la búsqueda de jndi se realiza con el nombre - "LibraryPersistenceBean / remote" para obtener el objeto comercial remoto (EJB sin estado).
Luego, se muestra al usuario una interfaz de usuario de la tienda de la biblioteca y se le pide que ingrese una opción.
Si el usuario ingresa 1, el sistema solicita el nombre del libro y guarda el libro usando el método addBook () del bean de sesión sin estado. Session Bean está almacenando el libro en la base de datos.
Si el usuario ingresa 2, el sistema recupera libros usando el método getBooks () del bean de sesión sin estado y sale.
Ejecute el cliente para acceder a EJB
Busque EJBTester.java en el explorador de proyectos. Haga clic derecho en la clase EJBTester y seleccionerun file.
Verifique la siguiente salida en la consola de Netbeans.
run:
**********************
Welcome to Book Store
**********************
Options
1. Add Book
2. Exit
Enter Choice: 1
Enter book name: learn html5
Enter Author name: Robert
**********************
Welcome to Book Store
**********************
Options
1. Add Book
2. Exit
Enter Choice: 2
Book(s) entered so far: 1
1. learn html5
Author: Robert
BUILD SUCCESSFUL (total time: 21 seconds)