JPA学习笔记-EJB-01JPA初体验

来源:互联网 发布:淘宝客教程 编辑:程序博客网 时间:2024/06/05 18:13

1. 前言:
本文是学习JPA 笔记,可能会根据自己的学习进度逐渐完善。学习中使用的持久层技术
是EJB,JPA 注解方式,底层应用的是Hibernate 实现和MySql 数据库,应用服务器采
用的是JBoss 4.2.0。随着笔者的学习笔记,大家一起学习吧,还是那句话,有什么问题
大家一起探讨。有什么错误希望指证!谢谢。
2. 环境
先准备好数据库和JBoss 应用服务器,将JBoss 和MyEclipse 的应用服务器集成起来(不
好意思,笔者最喜欢用MyEclipse)集成步骤如下图:

 

 

好的,下面建立一个Web 项目吧,取名字就叫做JPAEJB,之后加入环境需要的jar 包,
jar 包的目录如下,CSDN 只能允许上传20mb 的附件,所以只能先列出jar 包的列表。

/JPAEJB/WEB-INF/lib/activation.jar
/JPAEJB/WEB-INF/lib/antlr.jar
/JPAEJB/WEB-INF/lib/avalon-framework.jar
/JPAEJB/WEB-INF/lib/commons-codec.jar
/JPAEJB/WEB-INF/lib/commons-httpclient.jar
/JPAEJB/WEB-INF/lib/commons-logging.jar
/JPAEJB/WEB-INF/lib/concurrent.jar
/JPAEJB/WEB-INF/lib/ejb3-persistence.jar
/JPAEJB/WEB-INF/lib/getopt.jar
/JPAEJB/WEB-INF/lib/hibernate-annotations.jar
/JPAEJB/WEB-INF/lib/hibernate-client.jar
/JPAEJB/WEB-INF/lib/jacorb.jar
/JPAEJB/WEB-INF/lib/javassist.jar
/JPAEJB/WEB-INF/lib/jaxb-api.jar
/JPAEJB/WEB-INF/lib/jaxb-impl.jar
/JPAEJB/WEB-INF/lib/jaxb-xjc.jar
/JPAEJB/WEB-INF/lib/jboss-annotations-ejb3.jar
/JPAEJB/WEB-INF/lib/jboss-aop-jdk50-client.jar
/JPAEJB/WEB-INF/lib/jboss-aspect-jdk50-client.jar
/JPAEJB/WEB-INF/lib/jboss-client.jar
/JPAEJB/WEB-INF/lib/jboss-common-client.jar
/JPAEJB/WEB-INF/lib/jboss-deployment.jar
/JPAEJB/WEB-INF/lib/jboss-ejb3-client.jar
/JPAEJB/WEB-INF/lib/jboss-ejb3x.jar
/JPAEJB/WEB-INF/lib/jboss-iiop-client.jar
/JPAEJB/WEB-INF/lib/jboss-j2ee.jar
/JPAEJB/WEB-INF/lib/jboss-jaxrpc.jar
/JPAEJB/WEB-INF/lib/jboss-jaxws.jar
/JPAEJB/WEB-INF/lib/jboss-jsr77-client.jar
/JPAEJB/WEB-INF/lib/jboss-remoting.jar
/JPAEJB/WEB-INF/lib/jboss-saaj.jar
/JPAEJB/WEB-INF/lib/jboss-serialization.jar
/JPAEJB/WEB-INF/lib/jboss-srp-client.jar
/JPAEJB/WEB-INF/lib/jboss-system-client.jar
/JPAEJB/WEB-INF/lib/jboss-transaction-client.jar
/JPAEJB/WEB-INF/lib/jboss-xml-binding.jar
/JPAEJB/WEB-INF/lib/jbossall-client.jar
/JPAEJB/WEB-INF/lib/jbosscx-client.jar
/JPAEJB/WEB-INF/lib/jbossha-client.jar
/JPAEJB/WEB-INF/lib/jbossjmx-ant.jar
/JPAEJB/WEB-INF/lib/jbossmq-client.jar
/JPAEJB/WEB-INF/lib/jbosssx-client.jar

/JPAEJB/WEB-INF/lib/jbossws-client.jar
/JPAEJB/WEB-INF/lib/jbossws-wsconsume-impl.jar
/JPAEJB/WEB-INF/lib/jmx-client.jar
/JPAEJB/WEB-INF/lib/jmx-invoker-adaptor-client.jar
/JPAEJB/WEB-INF/lib/jnp-client.jar
/JPAEJB/WEB-INF/lib/log4j-1.2.15.jar
/JPAEJB/WEB-INF/lib/logkit.jar
/JPAEJB/WEB-INF/lib/mail.jar
/JPAEJB/WEB-INF/lib/scout.jar
/JPAEJB/WEB-INF/lib/servlet-api.jar
/JPAEJB/WEB-INF/lib/stax-api.jar
/JPAEJB/WEB-INF/lib/trove.jar
/JPAEJB/WEB-INF/lib/wsdl4j.jar
/JPAEJB/WEB-INF/lib/wstx.jar
/JPAEJB/WEB-INF/lib/xmlsec.jar
/JPAEJB/WEB-INF/lib/antlr-2.7.6.jar
/JPAEJB/WEB-INF/lib/asm-attrs.jar
/JPAEJB/WEB-INF/lib/asm.jar
/JPAEJB/WEB-INF/lib/cglib-2.1.3.jar
/JPAEJB/WEB-INF/lib/commons-collections-2.1.1.jar
/JPAEJB/WEB-INF/lib/commons-logging-1.0.4.jar
/JPAEJB/WEB-INF/lib/dom4j-1.6.1.jar
/JPAEJB/WEB-INF/lib/ehcache-1.2.3.jar
/JPAEJB/WEB-INF/lib/hibernate-commons-annotations.jar
/JPAEJB/WEB-INF/lib/hibernate-entitymanager.jar
/JPAEJB/WEB-INF/lib/hibernate-validator.jar
/JPAEJB/WEB-INF/lib/hibernate3.jar
/JPAEJB/WEB-INF/lib/jaas.jar
/JPAEJB/WEB-INF/lib/jaxen-1.1-beta-7.jar
/JPAEJB/WEB-INF/lib/jboss-archive-browsing.jar
/JPAEJB/WEB-INF/lib/jdbc2_0-stdext.jar
/JPAEJB/WEB-INF/lib/jta.jar
/JPAEJB/WEB-INF/lib/junit.jar
/JPAEJB/WEB-INF/lib/xerces-2.6.2.jar
/JPAEJB/WEB-INF/lib/xml-apis.jar
/JPAEJB/WEB-INF/lib/mysql-connector-java-5.1.10-bin.jar
这些jar 包大多数在hiberntae、jboss、apache、mysql 等开源项目的lib 下面获取。有机
会笔者会将jar 发布到附件比较大的论坛上,抱歉~~~
现在,基本上一个简单的EJB-JPA 环境已经配置好了,下面我们开始JPA 的开发旅程吧。
3. 开发EJB 实体Bean
在src 下面建立eo 文件夹,之后建立一个类似于POJO 的对象,代码如下:

package eo;
import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "tb_customer")
public class CustomerEO implements Serializable {
/**
*
*/
private static final long serialVersionUID = -6746637486454652006L;
private Integer id;
private String name;
public CustomerEO(){
}
@Id
@Column(name = "id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
以上代码就是一个实体Bean,既然是实体Bean 就得实现Serializable,否则此Bean
不能被序列化,也就是说不能持久化在远端EJB 容器中。更别说通过消息队列反序列化成
对象了,所以必须实现此Serializable 接口。之后应该默认有一个无参数的构造函数(建
议:最好有,否则会调用父类的无参构造函数)。

下面就是解释JPA注解了,
@Entity注解,告诉编译器,此类不是一个普通的类,它是代表一个关系型数据库表的实体类
(注:JPA对面向对象的数据库支持的怎么样,笔者没有求证过,暂时不清楚!但是很不幸,笔
者在公司用过mongodb---一种对象型数据库,以JSON的形式存储记录。公司的做法是将所有
的JPA全部都剔除掉,由此可见JPA对非关系型数据库支持的还不是那么理想)。那么像这样类
的对象就可以被JPA自己的接口所识别,调用JPA的接口就可以达到JBDC操作关系表的作用了。
@Table(name = "tb_customer"),这个很简单,告诉JPA接口,这个类对应的是哪张表,
此时在关系型数据库中表明显而易见就是叫做“tb_customer”。如图,Mysql管理界面。

 

@Id,表示此属性在表的那边是主键,只要是实体Bean,必须有此主键注解,也就是说JPA的规
范:每张实体表必须得有主键,这个和我们自己Create表是不一样的,自己建表,可以存在没
有主键的情况,但是JPA规范就是如此,必须有主键!至于复合主键的情况,留给以后咱们学习。
@Column(name = "id")就是表明类中的属性对应关系表中的哪个字段,表结构如下图

 

此时我们将一个实体Bean写完了,那么按照业务需要,针对于这个实体Bean,应该编写DAO类。
我们暂时简单一些,就只先编一个保存方法,将记录保存到数据库中就算成了。
4. 开发DAO 业务Bean
下面在src下面建立dao包,先写一个接口:

package dao;
import javax.ejb.Remote;
import eo.CustomerEO;
@Remote
public interface ICustomerService {
public void save (CustomerEO customerEO);
}
可以看到此接口有一个@Remote注解,这是EJB自己的注解,代表此接口是在远程的服务器上部
署的,和真正调用的客户端耦合的只是接口。这个道理和Web Service是一样的。客户端需要
服务端提供服务,那么客户端只需要知道服务端提供的服务接口以及参数就可以了,具体服务实
现,那是服务端的事情,客户端不需要关心。在这里就是客户端需要远程的DAO接口提供增删改
查的服务,那么你服务端具体的增删改查业务实现和我客户端无关,客户端只需要知道你的接口
说明,传进参数,能调用成功就行。(如果读者稍微了解一些EJB2.X的知识,就知道这个@Remote
注解为开发者省去了多少复杂的配置)
下面在dao报下面建立一个impl包,创建一个类实现此接口,代码如下:
package dao.impl;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import dao.ICustomerService;
import eo.CustomerEO;
@Stateless
public class CustomerServiceImpl implements ICustomerService {
@PersistenceContext(unitName = "JPAEJBPU")
private EntityManager entityManager;
public void save(CustomerEO customerEO) {
entityManager.persist(customerEO);
}
}
@Stateless:代表是一个无状态的实现接口,这个回头逐渐地深入学习,再讨论……
7
@PersistenceContext(unitName = "JPAEJBPU"):代表使用JPA容器注入的方式将JPA
实体管理类注入到此DAO实现类中来,这个旧类似于Spring的依赖注入(IOC)。unitName =
"JPAEJBPU"中的JPAEJBPU是和JPA的配置文件中一致。至于EntityManager这个类,各位
读者,您就暂时先当成Hibernate的Session使用就成了。它封装了JPA自己的接口,使用这
些接口方法,即可完成增删改查操作。例如上面的persist方法就是持久化customerEO对象、
将相应的记录写入数据库、事务提交等等操作。
现在为止,代码就写到这里,还需要加入一个配置文件才能顺利使用JPA。在src下面建立
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">
<persistence-unit name="JPAEJBPU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/jpaDemo</jta-data-source>
<properties>
<property name="hibernate.dialect"
value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
一看便知,这个配置文件是用来配置数据源的信息的。
我的代码结构如下图:

 

 

 

5. 部署EJB 项目
下面用资源管理器打开你的JBoss 文件夹,我的JBoss 放在了,E:/server/jboss-4.2.0.GA
下面,打开E:/server/jboss-4.2.0.GA/server/default/deploy,在此文件夹下面建立一个文件
叫做mysql-ds.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- $Id: mysql-ds.xml 41016 2006-02-07 14:23:00Z acoliver $ -->
<!-- Datasource config for MySQL using 3.0.9 available from:
http://www.mysql.com/downloads/api-jdbc-stable.html
-->
<datasources>
<local-tx-datasource>
<jndi-name>jpaDemo</jndi-name>
<connection-url>jdbc:mysql://127.0.0.1:3306/ejbjpa?useUnicode=true&amp;characterEncoding=
UTF-8</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>root</user-name>
<password>root</password>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</ex
ception-sorter-class-name>
<metadata>
<type-mapping>mySQL</type-mapping>
</metadata>
</local-tx-datasource>
</datasources>
这个文件的作用就是,应用服务器的数据源配置jndi-name 元素的值要和你自己的JPA
9
程序配置文件中的<jta-data-source> java:/xxxxxx 后面的名称要一致哦。
最后我们把自己的程序打成jar 包,放到E:/server/jboss-4.2.0.GA/server/default/deploy 下
面就可以了。这样我的E:/server/jboss-4.2.0.GA/server/default/deploy 文件夹如下:

 

 

可以看到,多了mysql-ds.xml 和JPAEJB.jar,2 个文件。
6. 测试
我们写一个测试程序来看看我们的程序是否正常运行吧。利用JUnit 测试,代码如下:
package client;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
import junit.framework.TestCase;
import dao.ICustomerService;
import eo.CustomerEO;
public class TestJPAEJBDAO extends TestCase{
private static Context context;
public void test01() {
try {
Context ctx = getInitialContext();
Object object = ctx.lookup("CustomerServiceImpl/remote");
ICustomerService customerService = (ICustomerService)
PortableRemoteObject
.narrow(object, ICustomerService.class);
10
CustomerEO customerEO = new CustomerEO();
customerEO.setId(2);
customerEO.setName("素还真");
customerService.save(customerEO);
} catch (NamingException e) {
e.printStackTrace();
}
}
/**
* 得到JBoss应用服务器容器上下文
* @return
* @throws NamingException
*/
public static Context getInitialContext() throws NamingException {
if (context == null) {
Hashtable<String,String> pros = new
Hashtable<String,String>();
pros.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
pros.put(Context.URL_PKG_PREFIXES,
"org.jboss.naming:org.jnp.interfaces");
pros.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099");
context = new InitialContext(pros);
}
return context;
}
}
启动一下JBoss 服务器,运行一下这个程序吧。运行后结果如下:

 

 

 

可以看到记录已经插进去了,到此我们对于JPA 简单的接口和EJB 部署已经有了了解,
以后继续学习,还会和大家分享,夜深了~~~~~2010-8-7 2:29。晚安………………