初次接触EJB
来到互联网公司,需要开发EJB程序,用两天的时间先学习了EJB的开发流程,我用的开发环境是myeclipse、jboss4.2、ejb3.0、struts1.3.8、jkd6、oracle、JPA,页面展现用到velocity。其实这不是一个春对ejb的学习文章,因为里面涉及了跟ejb无关的struts、velocity,如果单纯学习写ejb的helloword,数据库都不用连接。下面我描述下helloword程序的实现过程。
1. 在myeclipse下创建工程
右键myeclipse--创建工程,选择Enterprise java Project,输入工程名字,如"firstApp",勾选“new web module project”和"new ejb project“两项,eclipse会自动创建出相关联的三个工程:"firstApp"、"firstAppEJB"、"firstAppWeb";如下图所示:
2. 创建数据库表
我用的是oracle数据库,创建了一个名为test_yay_user的数据库表,里面有三个字段id、username、password,都是varchar类型。
3. 在jboss里面配置数据源(略去)
4. 在ejb工程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 ="OracleDS" transaction-type ="JTA" >
< jta-data-source >java:OracleDS </ jta-data-source >
< properties >
< property name ="hibernate.show_sql" value ="true" ></ property >
< property name ="hibernate.format_sql" value ="true" ></ property >
< property name ="hibernate.dialect" value ="org.hibernate.dialect.Oracle9Dialect" ></ property >
</ properties >
</ persistence-unit >
</ persistence >
< 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 ="OracleDS" transaction-type ="JTA" >
< jta-data-source >java:OracleDS </ jta-data-source >
< properties >
< property name ="hibernate.show_sql" value ="true" ></ property >
< property name ="hibernate.format_sql" value ="true" ></ property >
< property name ="hibernate.dialect" value ="org.hibernate.dialect.Oracle9Dialect" ></ property >
</ properties >
</ persistence-unit >
</ persistence >
其中 OracleDS 是你在jboss里面配置的数据源,其他参数根据具体起进行修改;
5. 创建持久化类
因为用到jpa,需要创建持久化类,因为用了注解的方式,没有对应的xml文件,文件如下:
package user;
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 = "test_yay_user")
public class User implements java.io.Serializable{
private static final long serialVersionUID = -8692000975878306489L;
private String id;
private String username;
private String password;
public User(){
}
public User(String id,String username,String password){
this.id = id;
this.username = username;
this.password = password;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false, length = 100)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Column(name = "username", nullable = false, length = 19)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Column(name = "password", nullable = false, length = 19)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
注意:好像必须要有那个全的构造函数,否则可能无法正确持久化;好像在我调试过程中,提示我必须要有个默认的构造函数;因为涉及到对象序列化,可能必须要有
serialVersionUID ;
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 = "test_yay_user")
public class User implements java.io.Serializable{
private static final long serialVersionUID = -8692000975878306489L;
private String id;
private String username;
private String password;
public User(){
}
public User(String id,String username,String password){
this.id = id;
this.username = username;
this.password = password;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false, length = 100)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Column(name = "username", nullable = false, length = 19)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Column(name = "password", nullable = false, length = 19)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
GenerationType.AUTO 是让数据库自己去决定主键的生产策略。
6. 在src根目录下创建jndi.properties
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming\:org.jnp.interfaces
7.
SessionBean的编写java.naming.provider.url=localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming\:org.jnp.interfaces
(1) 编写接口IUserService
里面声明增删改查的方法,接口最上方用@Remote声明,代码如下:
package user;
import javax.ejb.Remote;
import util.Page;
@Remote
public interface IUserService {
public void saveOrUpdate (User user);
public void delete (String userId);
public User getUser(String userId);
public Page queryPage( int pageNo, int pageSize);
}
(2) 编写实现类UserService
import javax.ejb.Remote;
import util.Page;
@Remote
public interface IUserService {
public void saveOrUpdate (User user);
public void delete (String userId);
public User getUser(String userId);
public Page queryPage( int pageNo, int pageSize);
}
实现增删改查的方法,接口最上方用@Stateless 和 @Remote(IUserService.class) 声明,类第一行代码是@PersistenceContext(unitName="OracleDS") EntityManager em;
程序会寻找OracleDS的数据源,然后初始化一个EntityManager对象,这个对象就是用来操作数据库,类似hibernate里面的hibernateTemplate,跟hibernate操作非常相像,如增加一个对象em.persist(obj);。
特殊说明:其实在初学把数据库的增删改查写在这个userService里面即可,但因为领导要求,我啰嗦了一层,userService会调用DAOFactory里面的方法,而DAOFactory里面的方法才调用EntityManager 去实现增删改查。
至此EJB工程已经开发完成。下面是客户端工程firstAppWeb开发。
1. 对于struts,velocity的引用就不多说了。
同样在src下加入jndi.properties配置文件;
2. 编写UserAction类,这个类要调用EJB工程的BEAN来完成增删改查操作。
首先是获得Context对象,然后lookup你要调用的EJB端的bean名称,如userService = (IUserService) ctx.lookup("UserService/remote");,这样就获取到了EJB工程里面的UserService,就可以向调用本地方法一样去调用了。
代码开发完成后,就该部署了。
我是直接用myeclipse的工具来发布的,发布后在jboss\server\default\deploy下会出现我们的工程文件夹firstApp.ear,里面包含EJB工程firstAppEJB.jar和WEB工程firstAppWeb.war。
然后启动jboss,在这里我折磨了五六个小时,始终报错”
javax.naming.NameNotFoundException
:xxxx not bound”,
最后看到文章http://blog.163.com/zzk331@126/blog/static/142674599200957111441126/
才解决,原来EJB工程发布后,必须要以jar形式存在,而不能以文件夹形式存在。
jboss正常启动后,运行系统,界面如下:
说明:网上很多文章都说要用ejb-jar配置文件盒jboss.xml配置文件,好像不用也可以,因为@remote这些注解就完成了配置文件的作用。
还有很多文章说把jboss/client下的所有jar方到web工程里面,再把EJB工程打包,也方到WEB工程里面,这样放置后,可以直接在web工程里面创建一个类,写main函数来调用已发布的EJB工程,但发布web工程的时候不应该将这些jar打包进去,因为jboss里面本来就有,或许会冲突;还因为EJB工程和我们的WEB工程在同一个虚拟机里面,所以也不用把EJB打包方到WEB工程下。
源代码下载 /Files/yangaiyou/firstApp.rar