在上一篇文章中,我们学习了EJB的会话bean,这篇文章我们来说一下EJB的实体bean,说到实体bean,就不得不说JPA了,JPA是在EJB3.0的时候提出来的,但是他不局限于EJB3.0,而是适用于整个J2EE,他是一种规范。
JPA定义了一系列的注解,@Entity,@Table,@Id @Colume等,当一个POJO类加上这些注解后,他就形成了实体bean。
我们看一下实体bean在程序中是怎么应用的呢。如果我们需要使用EJB调用实体Bean,那么我们就需要配置数据源,不知道大家有没有疑问,为什么以前做普通javaweb项目的时候,我们直接在程序中的配置文件中指定数据源就好了,为什么要去服务器上指定呢!配置JBoss数据源,为什么要在JBoss中配置数据源?这其实是面向对象思想的一种体现:通过容器管理对数据库的访问。
最开始我们通过JDBC访问数据库,什么Connection、Command都由我们自己创建。但每次打开关闭数据库很消耗资源,于是出现了数据库连接池,提前建立好对数据库的连接,用的时候去连接池取,用完了送回到连接池。这样虽然解决了资源消耗问题,但连接过程仍需要手动干预。后来在用Spring整合Hibernate时,出现了用Spring的IOC容器管理Hibernate对数据库的访问的思想,这个过程好比用Tomcat管理Servlet的生命周期。我们只需用Servlet完成消息的提交,不必要关心它什么时候创建、什么销毁,JBoss管理数据源也是相同的思想。那么我们看见如何配置JBoss数据源!
我们在jboss-6.1.0.Final\docs\examples\jca下找到你要使用数据库对应的数据源配置,我们使用的是mysql数据库,所以使用的是mysql-ds.xml配置文件。我们拷贝这个文件到部署项目的文件夹jboss-6.1.0.Final\server\default\deploy下边。内容如下!
<?xml version="1.0"encoding="UTF-8"?> <datasources> <local-tx-datasource> <!--JNDI的名字,我们通过该名字可以查找到改数据源--> <jndi-name>MySqlDS</jndi-name> <!--mySQL的连接字符串--> <connection-url>jdbc:mysql://localhost:3306/ejb3</connection-url> <!--mySQL的连接驱动--> <driver-class>com.mysql.jdbc.Driver</driver-class> <!--mySQL的连接用户名--> <user-name>root</user-name> <!--mySQL的连接密码--> <password>root</password> <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name> <metadata> <type-mapping>mySQL</type-mapping> </metadata> </local-tx-datasource> </datasources>
这样我们的数据源就配置好了, 如果你在程序中需要多个数据源的话,那么我们可以配置多个<local-tx-datasource>…..</local-tx-datasource>,但是如果是不同的数据库,例如Oracle数据库,我们可以在复制一份oracle-ds.xml文件到jboss-6.1.0.Final\server\default\deploy,或者将里边的内容的<local-tx-datasource>…..</local-tx-datasource>节点的所有内容放入到mysql-ds.xm文件中。
配置完数据源后我们就可以写程序了。我们建立一个EJB3的项目,然后在项目中META-INF文件夹下建立persistence.xml文件。该文件主要的作用就是配置数据源,然后在设置一些关于数据源的信息。内容如下!
<?xml version="1.0" encoding="UTF-8"?> <persistence 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" version="1.0"> <!-- 持久化单元的名字,可以随便起 transaction-type表示使用事务的类型,有JTA和RESOURCE_LOCALJTA和 RESOURCE_LOCAL的区别就在于一个是声明性事务管理,由容器来打理你添加了 @TransactionAttribut(xxxx) 注释的EJB method过程,而另一个需要手动从EM中得到一个事务句柄并使用begin(),commit()之类编程性事务管理方式 --> <persistence-unit name="user" transaction-type="JTA"> <!-- 数据源,就是上文中mysql-ds.xml中配置的名称,因为该数据源放在jboss下,所以加了前缀java:/ 如果此处不加的话, 在后边依赖查找的时候要加上! --> <jta-data-source>java:/MySqlDS</jta-data-source> <properties> <!-- 配置数据源的属性,应该jboss的底层是采用Hibernate实现的,所以采用我们 熟悉的hibernate的配置方式。如果不了解的话, 可以自己去查一下资料 --> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence>
配置完持久化信息后,我们建立我们的实体bean。我们的@Entity和@Table配置在类的上边,表示这个是一个实体类。至于@id和@column既可以配置属性上,也可以配置在get set 方法上,效果都是一样。再有只要标示了@id,@Column是可以省略的!
@Entity @Table(name="t_user") public class User implements Serializable{ @Id @GeneratedValue(strategy=GenerationType.IDENTITY) privateInteger id; //设置属性userCode对应的字段为user_code,长度为32,非空 @Column(name= "username", nullable = false, length=32) privateString userName; @Column privateString password; @Column privateString att; publicInteger getId() { returnid; } publicvoid setId(Integer id) { this.id= id; } publicString getUserName() { returnuserName; } publicvoid setUserName(String userName) { this.userName= userName; } publicString getPassword() { returnpassword; } publicvoid setPassword(String password) { this.password= password; } publicString getAtt() { returnatt; } publicvoid setAtt(String att) { this.att= att; } }
我们在建立SessionBean,代码如下所示,并将程序发布到Jboss服务器中。
public interface UserManager { public void addUser(User user); } @Remote @Stateless public class UserManagerBean implements UserManager { //持久化上下文,名字为persistence.xml中配置的名字。 此处使用依赖注入,他的事务由容器管理 //实体管理,类似于Hibernate中的session @PersistenceContext(name="user") private EntityManager em; @Override public void addUser(User user) { //循环插入十条数据! for (int i = 0; i < 10; i++) { //持久化保存到数据库中 em.persist(user); //验证事物是否可行!能否进行回滚。 /*if (i==5) { throw new RuntimeException(); }*/ } } }
然后建立客户端,代码如下所示,
package com.tgb.client; import java.util.Properties; import javax.naming.InitialContext; import javax.naming.NamingException; import com.tgb.domain.User; import com.tgb.manager.UserManager; public class EntityBeanClient { public static void main(String[] args) { Properties props = new Properties(); props.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory"); props.setProperty("java.naming.provider.url", "localhost:1099"); try { //建立上下文 InitialContext ctx = new InitialContext(props); UserManager userManager =(UserManager) ctx.lookup("UserManagerBean/remote"); User user = new User(); user.setUserName("zhj"); user.setPassword("0302"); user.setAtt(""); userManager.addUser(user); } catch (NamingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
我们可以看到数据已经插入到数据库中!EJB的实体Bean是借助了JPA来实现的!所以要想用法ejb的实体bean ,就要学习JPA!