EJB3.0学习总结
今天是五一的第二天。最近这段时间在研究EJB3.0,虽然EJB3.0已经出来好些年了。以前在学校的时候也听过一些有关EJB开发,但是从未研究过。来到公司之后由于公司使用的就是EJB开发了。所以学起了EJB
前段时间也有学习一些有关EJB的基本概念:EJB(Enterprise JavaBean)也即企业JavaBean。其主要分为三种Bean:Entity Bean、Session Bean(Stateless bean and StateFull bean)、Driver-Message Bean。
Entity Bean:也即我们的一般java 对象
Session Bean:处理业务的service bean
Driver-Message Bean:发送处理业务的消息
EJB主要是工作在容器中,目前主流服务器实现了对EJB的支持的有:IBM的Websphere 、JBOSS等等。我使用的是JBOSS
当我们声明一个普通的实现业务处理的对象为Session bean的时候,其主要有两种:Remote和Local两种接口。当JBoss和EJB在同一个JVM的时候我们一般使用Local接口。当他们不是同一个JVM的时候需要使用Remote接口。
实际开发中,EJB3.0往往和Ant(一种构建工具),Jboss结合使用,这样可以提高开发效率。不然每次我们都需要将EJB重新部署到JBoss中,有了Ant构建工具我们就可以直接在Outline---->下面对应的Ant 名直接部署。可以动态的更新。EJB3.0以后使用更加方便了,当我们读取一个JNDI的时候,只需要配置一个jndi.properties文件,在加载JNDI的时候只需要两行代码即可实现:
InitialContext ctx=new InitialContext();
UserService userService=(UserService)ctx.lookup("UserServiceImpl/remote");
从而我们就可以得到相应的EJB的Bean,从而实现相关操作。
JPA(Java Persistent API)java持久化API,其在EJB中的使用相当广泛。下面一EJB3.0开发单表映射的实体bean为例子
新建一个普通的java Project 定义一个Entity Bean
package com.clark.model;
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
* @author Administrator
*
*/
@Entity
/**
* 注解的方式映射表和实体对象
* @author Administrator
*
*/
@Table(name="user")
public class User implements Serializable{
private static final long serialVersionUID = 5022340816599863071L;
private int userId;
private String userName;
//Id标识该table的主键对应的Entity
@Id
@Column(name="user_id",length=11,nullable=false)
//主键生成策略 AUTO的话可移植性好,可以根据自身所使用的主键策略自动判断
@GeneratedValue(strategy=GenerationType.AUTO)
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
@Column(name="user_name",length=10,nullable=true)
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + userId;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (userId != other.userId)
return false;
return true;
}
//JPA规范要求
public User(){
}
public User(String userName) {
this.userName = userName;
}
}
Entity Bean ------------------------------------------------>对应的Session Bean 无状态的UserService 接口
package com.clark.service;
import java.util.List;
import com.clark.model.User;
/**
* 业务处理
* @author Administrator
*
*/
public interface UserService {
public void save(User user);
public void update(User user);
public void delete(int userId);
public User findById(int userId);
public List<User> findUserList();
}
实现Stateless的StateFull Bean
package com.clark.service.impl;
import java.util.List;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import com.clark.model.User;
import com.clark.service.UserService;
@Stateless
@Remote(UserService.class)
public class UserServiceImpl implements UserService {
/**
* 持久化管理,当我们配置了多个persistent-unit的时候需要指定name
*/
@PersistenceContext(name="clark") EntityManager em;
public void save(User user) {
//调用em对象直接保存
em.persist(user);
}
public void update(User user) {
em.merge(user);
}
public void delete(int userId) {
//em.getReference(User.class, userId)返回一个代理对象,若是不存在该对象则直接抛出异常
em.remove(em.getReference(User.class, userId));
}
public User findById(int userId) {
return em.find(User.class, userId);
}
@SuppressWarnings("unchecked")
public List<User> findUserList() {
//面向对象变成思想from 对象名
return em.createQuery("select u from User u").getResultList();
}
}
src 下新建一个META-INF文件夹--------------文件夹下面再新建一个persistence.xml文件:注意该文件必须要有---------其是实现JPA的必须
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
<!-- 持久化单元,就是一群Entity的集合
EJB的默认事物处理类型是JPA全局事物
-->
<persistence-unit name="clark" transaction-type="JTA">
<!-- 数据源的配置必须也要有,在次操作之前要配好-->
<!-- 配置一个数据源 提高操作数据库的性能
因为之前添加的数据源是在java:的命名空间下,而且配置的
数据源名称为clarkDS
-->
<jta-data-source>java:clarkDS</jta-data-source>
<!-- JPA实现EJB是利用的Hibernate的原理 故可以配置Hibernate相关属性 -->
<properties>
<!-- 配置可以在更新的时候创建Entity对应的数据库中的表 -->
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
此外也需要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
结合Junit来对进行单元测试:引入相关的Junit jar包,此外,也必须要将D:\JBoss\jboss-4.2.3.GA\client\所有的jar包引入项目中,另外附带mysql的驱动包(我是使用mysql数据库了)
package junit.test;
import java.util.List;
import javax.naming.InitialContext;
import org.junit.BeforeClass;
import org.junit.Test;
import com.clark.model.User;
import com.clark.service.UserService;
public class UserServiceImplTest {
private static UserService userService;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
//得到EJB的Bean对象
InitialContext ctx=new InitialContext();
userService=(UserService)ctx.lookup("UserServiceImpl/remote");
}
@Test
public void testSave() {
userService.save(new User("张三"));
}
@Test
public void testUpdate() {
User user=userService.findById(2);
user.setUserName("XXX");
userService.update(user);
}
@Test
public void testDelete() {
userService.delete(2);
}
@Test
public void testFindById() {
userService.findById(1);
}
@Test
public void testFindUserList() {
List<User> users=userService.findUserList();
for (User user : users) {
System.out.println(user.getUserName());
}
}
}
最后:build.xml配置文件如下:
<?xml version="1.0" encoding="utf-8"?>
<!--定义一个项目 -->
<project name="EntityBean" basedir=".">
<!-- 定义一些属性-->
<!--project下面的src -->
<property name="src.dir" value="${basedir}\src"></property>
<!--系统的环境变量 -->
<property environment="env"></property>
<!-- 系统环境变量JBOSS_HOME配置-->
<property name="jboss.home" value="${env.JBOSS_HOME}"></property>
<!-- JBOSS服务的default默认配置-->
<property name="jboss.server.config" value="default"></property>
<!--项目下建立一个build -->
<property name="build.dir" value="${basedir}\build"></property>
<!--定义path -->
<path id="build.classpath">
<!-- 导进jboss安装目录下的client目录下的所有的jar包-->
<fileset dir="${jboss.home}\client">
<include name="*.jar"/>
</fileset>
<pathelement location="${build.dir}"/>
</path>
<!-- 定义一些target-->
<target name="prepare">
<!-- 若是已经存在则先删除-->
<delete dir="${build.dir}"></delete>
<mkdir dir="${build.dir}"/>
</target>
<!--编译配置 -->
<target name="compile" depends="prepare" description="编译">
<!--将src下面的java文件编译到指定 的目录下面生成class字节文件 includes编译的时候过滤条件 -->
<javac srcdir="${src.dir}" destdir="${build.dir}" includes="com/**">
<classpath refid="build.classpath"></classpath>
</javac>
</target>
<!-- 创建ejb配置-->
<target name="ejbjar" depends="compile" description="创建ejb发布包">
<jar destfile="${basedir}\${ant.project.name}.jar">
<fileset dir="${build.dir}">
<include name="**/*.class" />
</fileset>
<!--打成jar包的时候需要将META-INF下面的persistent.xml文件也加进来 -->
<metainf dir="${src.dir}\META-INF"></metainf>
</jar>
</target>
<!--部署ejb -->
<target name="deploy" depends="ejbjar" description="发布ejb">
<!--将生成的ejb发布到jboss下面 -->
<copy file="${basedir}\${ant.project.name}.jar" todir="${jboss.home}\server\${jboss.server.config}\deploy"></copy>
</target>
<!--卸载ejb -->
<target name="undeploy" depends="deploy" description="卸载ejb">
<delete file="${jboss.home}\server\${jboss.server.config}\deploy\${ant.project.name}.jar"></delete>
</target>
</project>