EJB的持久性
EJB 3,实体bean使用EJB 2很大程度上是由持久化机制取代。现在实体Bean是一种简单的POJO映射表。
以下是持续性的关键参与者的API:
1、实体 - 表示数据存储记录的持久化对象。它能很好的进行“可串行化”。
2、EntityManager坚持做界面的数据操作如添加/删除/更新/持久对象发现(实体)。它也有助于使用查询接口执行查询。
3、持久性单元(persistence.xml) 持久性单元描述了持久性机制的属性。
4、数据源(* ds.xml) - 数据源描述了数据存储相关的属性,比如URL链接。用户名,密码等。
为了演示EJB持久化机制,我们将执行以下任务:
步骤1.在数据库中创建表。
步骤2.创建与表对应的Entity(实体)类。
步骤3.创建数据源和持久性单元
步骤4.创建一个具有无状态EJB的EntityManager(依赖注入)实例。
步骤5.更新无状态EJB。添加方法为通过实体管理器添加记录,并从数据库中获取记录。
步骤6.基于控制台的应用程序客户端将访问无状态的EJB以将数据保存到数据库中。
创建表
创建一个tablebooksin默认databasepostgres。
CREATE TABLE books(id integer PRIMARY KEY,name varchar(50));
创建实体类
//mark it entity using Entity annotation
//map table name using Table annoation@Entity@Table(name="books")publicclassBookimplementsSerializable{privateintid;privateStringname;publicBook(){}
//mark id as primary key with autogenerated value
//map database column id with id field@Id@GeneratedValue(strategy=GenerationType.IDENTITY)@Column(name="id")publicintgetId(){returnid;}...}
创建数据源和存储单元
数据源(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)
<persistenceversion="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-unitname="EjbComponentPU"transaction-type="JTA"><jta-data-source>java:/PostgresDS</jta-data-source><exclude-unlisted-classes>false</exclude-unlisted-classes><properties/></persistence-unit><persistence-unitname="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><propertyname="hibernate.hbm2ddl.auto"value="update"/></properties></persistence-unit></persistence>
@StatelesspublicclassLibraryPersistentBeanimplementsLibraryPersistentBeanRemote{//pass persistence unit to entityManager.@PersistenceContext(unitName="EjbComponentPU")privateEntityManagerentityManager;publicvoidaddBook(Bookbook){entityManager.persist(book);}publicList<Book>getBooks(){returnentityManager.createQuery("From Books").getResultList();}...}
在构建EJB模块之后,我们需要一个客户端来访问无状态bean,我们将在下一节中创建它。
示例应用程序
让我们创建一个测试EJB应用程序来测试EJB持久化机制。
EJBC组件(EJB模块)
Step | Description |
---|---|
1 | 在EJB - 创建一个Applicationchapter中解释的packagecom。再在tutorialspoint.entity下创建一个名为EJB Component的项目。 您还可以使用在EJB中创建的项目 - 创建Applicationchapter,以便了解本章EJB持久性概念 |
2 | CreateBook.javaunder packagecom.tutorialspoint.entityand修改如下所示。 |
3 | CreateLibraryPersistentBean.javaandLibraryPersistentBeanRemoteas在EJB中解释 - 创建Applicationchapter并修改它们如下所示。 |
4 | Createjboss-ds.xmlinEjbComponent> setupfolder andpersistence.xmlinEjbComponent> src> conffolder。 这些文件夹可以在Netbeans中的文件选项卡中看到。 修改这些文件,如上所示。 |
5 | 清理并构建应用程序以确保业务逻辑按照要求工作。 |
6 | 最后,在JBoss Application Server上以jar文件的形式部署应用程序。 如果JBoss应用程序服务器尚未启动,它将自动启动。 |
7 | 现在创建EJB客户端,一个基于控制台的应用程序,其方式与在EEB - 在ApplicationCreate Client下创建Applicationchapter以访问EJB中说明的方式相同。 修改它如下所示。 |
EJBC组件(EJB模块)
Book.java
packagecom.tutorialspoint.entity;importjava.io.Serializable;importjavax.persistence.Column;importjavax.persistence.Entity;importjavax.persistence.EntityListeners;importjavax.persistence.GeneratedValue;importjavax.persistence.GenerationType;importjavax.persistence.Id;importjavax.persistence.Table;@Entity@Table(name="books")publicclassBookimplementsSerializable{privateintid;privateStringname;publicBook(){}@Id@GeneratedValue(strategy=GenerationType.IDENTITY)@Column(name="id")publicintgetId(){returnid;}publicvoidsetId(intid){this.id=id;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}}
LibraryPersistentBeanRemote.java
packagecom.tutorialspoint.stateless;importcom.tutorialspoint.entity.Book;importjava.util.List;importjavax.ejb.Remote;@RemotepublicinterfaceLibraryPersistentBeanRemote{voidaddBook(BookbookName);List<Book>getBooks();}
LibraryPersistentBean.java
packagecom.tutorialspoint.stateless;importcom.tutorialspoint.entity.Book;importjava.util.List;importjavax.ejb.Stateless;importjavax.persistence.EntityManager;importjavax.persistence.PersistenceContext;@StatelesspublicclassLibraryPersistentBeanimplementsLibraryPersistentBeanRemote{publicLibraryPersistentBean(){}@PersistenceContext(unitName="EjbComponentPU")privateEntityManagerentityManager;publicvoidaddBook(Bookbook){entityManager.persist(book);}publicList<Book>getBooks(){returnentityManager.createQuery("From Book").getResultList();}}
1、在JBOSS上部署EjbComponent项目后,请注意jboss日志。
2、JBossJBoss已经为LibraryPersistentBean / remote自动创建了一个JNDI条目。
3、我们将使用这个查找字符串来获取类型为-com.tutorialspoint.stateless.LibraryPersistentBeanRemote的远程业务对象。
2、JBossJBoss已经为LibraryPersistentBean / remote自动创建了一个JNDI条目。
3、我们将使用这个查找字符串来获取类型为-com.tutorialspoint.stateless.LibraryPersistentBeanRemote的远程业务对象。
JBoss应用程序服务器日志输出
...16:30:01,401INFO[JndiSessionRegistrarBase]Bindingthe followingEntriesinGlobalJNDI:LibraryPersistentBean/remote-EJB3.xDefaultRemoteBusinessInterfaceLibraryPersistentBean/remote-com.tutorialspoint.stateless.LibraryPersistentBeanRemote-EJB3.xRemoteBusinessInterface16:30:02,723INFO[SessionSpecContainer]Startingjboss.j2ee:jar=EjbComponent.jar,name=LibraryPersistentBeanRemote,service=EJB316:30:02,723INFO[EJBContainer]STARTED EJB:com.tutorialspoint.stateless.LibraryPersistentBeanRemoteejbName:LibraryPersistentBean16:30:02,731INFO[JndiSessionRegistrarBase]Bindingthe followingEntriesinGlobalJNDI:LibraryPersistentBean/remote-EJB3.xDefaultRemoteBusinessInterfaceLibraryPersistentBean/remote-com.tutorialspoint.stateless.LibraryPersistentBeanRemote-EJB3.xRemoteBusinessInterface...
EJBTester(EJB客户端)
jndi.properties
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactoryjava.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfacesjava.naming.provider.url=localhost
1、这些属性用于初始化java命名服务的InitialContext对象
2、InitialContext对象将用于查找无状态会话bean
ejbtester.java
packagecom.tutorialspoint.test;importcom.tutorialspoint.stateless.LibraryPersistentBeanRemote;importjava.io.BufferedReader;importjava.io.FileInputStream;importjava.io.IOException;importjava.io.InputStreamReader;importjava.util.List;importjava.util.Properties;importjavax.naming.InitialContext;importjavax.naming.NamingException;publicclassEJBTester{BufferedReaderbrConsoleReader=null;Propertiesprops;InitialContextctx;{props=newProperties();try{props.load(newFileInputStream("jndi.properties"));}catch(IOExceptionex){ex.printStackTrace();}try{ctx=newInitialContext(props);}catch(NamingExceptionex){ex.printStackTrace();}brConsoleReader=newBufferedReader(newInputStreamReader(System.in));}publicstaticvoidmain(String[]args){EJBTesterejbTester=newEJBTester();ejbTester.testEntityEjb();}privatevoidshowGUI(){System.out.println("**********************");System.out.println("Welcome to Book Store");System.out.println("**********************");System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");}privatevoidtestEntityEjb(){try{intchoice=1;LibraryPersistentBeanRemotelibraryBean=LibraryPersistentBeanRemote)ctx.lookup("LibraryPersistentBean/remote");while(choice!=2){StringbookName;showGUI();StringstrChoice=brConsoleReader.readLine();choice=Integer.parseInt(strChoice);if(choice==1){System.out.print("Enter book name: ");bookName=brConsoleReader.readLine();Bookbook=newBook();book.setName(bookName);libraryBean.addBook(book);}elseif(choice==2){break;}}List<Book>booksList=libraryBean.getBooks();System.out.println("Book(s) entered so far: "+booksList.size());inti=0;for(Bookbook:booksList){System.out.println((i+1)+". "+book.getName());i++;}}catch(Exceptione){System.out.println(e.getMessage());e.printStackTrace();}finally{try{if(brConsoleReader!=null){brConsoleReader.close();}}catch(IOExceptionex){System.out.println(ex.getMessage());}}}}
EJBTester正在执行以下任务。
从jndi.properties加载属性并初始化InitialContext对象。
在testStatefulEjb()方法中,使用name - “LibraryStatefulSessionBean / remote”来完成jndi查找,以获取远程业务对象(有状态的ejb)。
然后用户显示图书馆商店用户界面,他/她被要求输入选择。
如果用户输入1,系统要求书名并使用无状态会话bean addBook()方法保存书。 会话Bean通过EntityManager在数据库中持久化调用这本书。
如果用户输入2,系统使用有状态会话Bean getBooks()方法检索书籍并退出。
然后,使用name - “LibraryStatelessSessionBean / remote”进行另一个jndi查找,以再次获取远程业务对象(无状态ejb),并完成书目列表。
在testStatefulEjb()方法中,使用name - “LibraryStatefulSessionBean / remote”来完成jndi查找,以获取远程业务对象(有状态的ejb)。
然后用户显示图书馆商店用户界面,他/她被要求输入选择。
如果用户输入1,系统要求书名并使用无状态会话bean addBook()方法保存书。 会话Bean通过EntityManager在数据库中持久化调用这本书。
如果用户输入2,系统使用有状态会话Bean getBooks()方法检索书籍并退出。
然后,使用name - “LibraryStatelessSessionBean / remote”进行另一个jndi查找,以再次获取远程业务对象(无状态ejb),并完成书目列表。
运行客户端以访问EJB
在项目资源管理器中找到EJBTester.java。 右键单击EJBTester类和selectrun文件。
在Netbeans控制台中验证以下输出。
在Netbeans控制台中验证以下输出。
run:**********************WelcometoBookStore**********************Options1.AddBook2.ExitEnterChoice:1Enterbook name:LearnJava**********************WelcometoBookStore**********************Options1.AddBook2.ExitEnterChoice:2Book(s)entered so far:11.learn javaBUILD SUCCESSFUL(total time:15seconds)
再次运行客户端以访问EJB
在访问EJB之前重新启动JBoss。
在项目资源管理器中找到EJBTester.java。 右键单击EJBTester类和selectrun文件。
在Netbeans控制台中验证以下输出。
在项目资源管理器中找到EJBTester.java。 右键单击EJBTester类和selectrun文件。
在Netbeans控制台中验证以下输出。
run:**********************WelcometoBookStore**********************Options1.AddBook2.ExitEnterChoice:1Enterbook name:LearnSpring**********************WelcometoBookStore**********************Options1.AddBook2.ExitEnterChoice:2Book(s)entered so far:21.learn java2.LearnSpringBUILD SUCCESSFUL(total time:15seconds)
上面显示的输出表明,书籍存储在持久性存储中,并从数据库中检索可以到。