`

EJB 3 初次学习小结

阅读更多
从昨天到今天晚上,从对EJB的不熟悉,到可以搭建出基于EJB一站式的HELLOWORLD(发出JNDI查找---业务BEAN----JPA查询----返回结果),花了大概接近15个小时的时间,收获非常大,第一就是部署,部署明显还是没有JAVA WEB来的快,来的爽。但是在学习过程中也体验到了一些快乐,EJB还是简单的,不过相对于SPRING这类DI框架来说,还是要复杂一些。

学习过程中,我首先把手头上的《EJB实战》,《企业级EJB》这2本书大概的翻阅了一下,之后就开始找DEMO学习,学习过程中,感到了网络上学习资料之少,包括出了异常的不知所云,再到自己一个一个解决,到最后EJB程序跑成,走出了一段非常艰难的历程,首先就是环境,我使用了EJB3+JBOSS5。由于对EJB整体概念的迷糊,一开始一个BEAN写好了,都不知道应该往哪里放,怎么样去打包,相比JAVA WEB的应用,责要烦人很多。另外,出了很多莫名其妙的异常,我还发现一个问题,异常一般提示很少,GOOGLE到的东西几乎都是英文网页,从这点也可以看出国内对EJB3的应用还是不多,不像SSH,一GOOGLE能出一大堆信息。终于,自己最后解决了部署问题。EJB组件单独打成JAR,之后把显示层打成WEB格式的WAR。因为在EJB中可以使用注解,所以感觉还是很爽的,可以比较容易的去写各种BEAN,包括可以使用注解把接口打包成JNDI服务。之后在展现层使用JNDI去掉业务层服务。一开始最郁闷的异常就是因为对EJB部署概念的不熟悉,导致了走了许多冤枉路,一直出这个异常(javax.naming.NameNotFoundException: UserBean not bound)代码没有问题,可是JBOSS一直不把这个JNDI注册为服务,问题就是出在部署上,我在EJB项目的META-INF文件夹里添加了不应该添加的东西,导致JBOSS始终不去加载这个服务。最后还不容易解决,又出了问题,一开始我把一个接口注解成本地服务,可是JNDI一直无法获取的这个接口,最后注解成了远程服务,终于搞定,我还奇怪来着。最后就是整个DEMO包的架构问题,以前一直使用SSH2的组合,一直把WEB层也写到项目里,一开始写EJB的DEMO,我也这么干了,呵呵,问题可想而知了。不过在走了许多弯路之后,还是改了。把EJB与展现层分开了,现在还没写SERVLET,只是写了个MAIN,做了个TEST,感受颇多啊,EJB是强大的,这点不用否认了。还有一点,现在EJB3的开发速度如果熟练,我认为还是挺快的,当然,我没有使用过SSH2的注解,一直都是以XML为中心,在EJB上都换成了注解,爽死。唯一需要XML的就是persistence.xml,找一下配置在JBOSS上的JNDI数据源。

上个DEMO的代码吧,也为打算学习EJB3的朋友开个头,少走点弯路。



首先是一个简单的泛型DAO,接口与服务类(没有事务处理,没有测试,LOAD是可以用的,哈哈):


package com.core.support.ejbDao;

import java.io.Serializable;
import java.util.List;

import javax.persistence.Query;

public interface IBaseDAO<T,PK extends Serializable> {
	
	
	/**
	 * 根据Id查找一个类型为T的对象。
	 * @param clazz
	 * @param id
	 * @return
	 */
	public T load(Serializable id);

	/**
	 * 把实体持久化到数据库,并且使实体受到管制。
	 * @param t
	 */
	public void persist(T t);

	/**
	 * 持久化一个对象,该对象类型为T。
	 * @param t
	 */
	public void save(T t);
	
	/**
	 * 根据对象id删除一个对象,该对象类型为T
	 * @param t
	 */
	public void delete(T t);
	
	/**
	 * 根据ID删除对象
	 * @param id
	 */
	public void deleteById(PK id);
	
	/**
	 * 更新一个对象,主要用于更新一个在persistenceContext之外的一个对象。
	 * 
	 * @param transientObject
	 *            需要更新的对象,该对象不需要在persistenceContext中。
	 */
	void update(T transientObject);
	
    
	public Query createQuery(String jpql);

	/**
	 * 根据JPQL查询总数
	 * @param jpql
	 * @return
	 */
	public int getTotalCount(String jpql);

	/**
	 * 使用JPQL进行查询
	 * @param jpql
	 * @return
	 */
	public List<T> find(String jpql);

	/**
	 * 单条件的JPQL查询
	 * @param jpql
	 * @param param
	 * @return
	 */
	public List<T> find(String jpql, Object param);

	/**
	 * 多条件的JPQL查询
	 * @param jpql
	 * @param param
	 * @return
	 */
	public List<T> find(String jpql, Object... param);
	
	/**
	 * 更新或添加
	 * @param t
	 */
	public void saveOrUpdate(T t);
	
	/**
	 * 实体分离
	 */
	public void flush();
}


package com.core.support.ejbDao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;


public class BaseDAOImpl<T,PK extends Serializable> implements IBaseDAO<T,PK> {
	
	private Class<T> clazz;
	
	// 构造方法,根据实例类自动获取实体类类型
	public BaseDAOImpl() {
        this.clazz = null;
        Class c = getClass();
        Type t = c.getGenericSuperclass();
        if (t instanceof ParameterizedType) {
            Type[] p = ((ParameterizedType) t).getActualTypeArguments();
            this.clazz = (Class<T>) p[0];           
        }
    }
	
	@PersistenceContext(unitName="OpenStarBBS")
	 protected EntityManager em;
	 
	
	 public Query createQuery(String jpql) {
	  return em.createQuery(jpql);
	 }
	 
	 public void delete(T t) {
	  em.remove(t);
	 }
	 
	 public T load(Serializable id) {
	  return em.find(clazz,id);
	 }
	 
	 @SuppressWarnings("unchecked")
	 public List<T> find(String jpql, Object param) {
	  return em.createQuery(jpql).setParameter(1, param).getResultList();
	 }
	 
	 @SuppressWarnings("unchecked")
	 public List<T> find(String jpql, Object[] param) {
	  Query query = em.createQuery(jpql);
	  for (int i = 1; i <= param.length; i++) {
	   query.setParameter(i, param[i - 1]);
	  }
	  return query.getResultList();
	 }
	 
	 
	 @SuppressWarnings("unchecked")
	 public List<T> find(String jpql) {
	  return em.createQuery(jpql).getResultList();
	 }
	 
	 
	 @SuppressWarnings("unchecked")
	 public int getTotalCount(String jpql) {
	  return ((Long) em.createQuery(jpql).getSingleResult()).intValue();
	 }
	 
	 
	 public void persist(T t) {
	  em.persist(t);
	 }
	 
	 
	 public void save(T t) {
	  em.merge(t);
	 }
	 
	 
	 public void saveOrUpdate(T t) {
	  em.merge(t);
	 }


	 public void update(T transientObject) {
		em.merge(transientObject);
		
	}

	public void deleteById(PK id) {
		T object = this.load(id);
		this.delete(object);	
	}

	public void flush() {
		em.flush();
	}
	
}


以上这个可以复用。下面就是程序里的接口和类:

JAP ORM映射类(用工具通过数据库逆向工程):
package com.openstarbbs.model;

import javax.ejb.EJB;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;

import javax.persistence.Id;
import javax.persistence.Table;

import com.core.support.ejbDao.IBaseDAO;

/**
 * User entity. @author MyEclipse Persistence Tools
 */
@Entity
@Table(name = "user", catalog = "openstarbbs")
public class User implements java.io.Serializable {

	// Fields

	private Integer id;
	private String name;
	private String age;

	@EJB
	private IBaseDAO baseDao;
	
	// Constructors

	/** default constructor */
	public User() {
	}

	/** full constructor */
	public User(String name, String age) {
		this.name = name;
		this.age = age;
	}

	public void saveUser(User user){
		baseDao.save(user);
	}
	
	// Property accessors
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "id", unique = true, nullable = false)
	public Integer getId() {
		return this.id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	@Column(name = "name", nullable = false, length = 45)
	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Column(name = "age", nullable = false, length = 45)
	public String getAge() {
		return this.age;
	}

	public void setAge(String age) {
		this.age = age;
	}

}


USER DAO,继承于泛型DAO。

package com.openstarbbs.user.dao;

import javax.ejb.Stateless;

import com.core.support.ejbDao.BaseDAOImpl;
import com.openstarbbs.model.User;

@Stateless
public class UserDao extends BaseDAOImpl<User,Long> implements IUserDao{

		
}


package com.openstarbbs.user.dao;

import javax.ejb.Local;

import com.core.support.ejbDao.IBaseDAO;
import com.openstarbbs.model.User;

@Local  
public interface IUserDao extends IBaseDAO<User,Long>{
	
}


业务层会话BEAN。

package com.openstarbbs.user.service;

import javax.ejb.Remote;

import com.openstarbbs.model.User;

@Remote
public interface IUserBean {
	
	public User getUser();
	
}


package com.openstarbbs.user.service;

import javax.ejb.EJB;
import javax.ejb.Remote;
import javax.ejb.Stateless;


import com.openstarbbs.model.User;
import com.openstarbbs.user.dao.IUserDao;


@Stateless
@Remote
public class UserBean implements IUserBean {
	
	@EJB
	private IUserDao userDao;
	
	public User getUser() {
		return userDao.load(1);
	}

}


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="OpenStarBBS" transaction-type="JTA">
  		<jta-data-source>java:/MySqlDS</jta-data-source>
  		<properties>
			<property name="hibernate.hbm2ddl.auto" value="update" />
			<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
		</properties>
  		
	</persistence-unit>
  
</persistence>



JBOSS数据源配置:

<?xml version="1.0" encoding="UTF-8"?>

<!-- See http://www.jboss.org/community/wiki/Multiple1PC for information about local-tx-datasource -->
<!-- $Id: mysql-ds.xml 88948 2009-05-15 14:09:08Z jesper.pedersen $ -->
<!--  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>MySqlDS</jndi-name>
    <connection-url>jdbc:mysql://localhost:3306/openstarbbs</connection-url>
    <driver-class>com.mysql.jdbc.Driver</driver-class>
    <user-name>root</user-name>
    <password>1234</password>
    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
    <!-- should only be used on drivers after 3.22.1 with "ping" support
    <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLValidConnectionChecker</valid-connection-checker-class-name>
    -->
    <!-- sql to call when connection is created
    <new-connection-sql>some arbitrary sql</new-connection-sql>
      -->
    <!-- sql to call on an existing pooled connection when it is obtained from pool - MySQLValidConnectionChecker is preferred for newer drivers
    <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
      -->

    <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
    <metadata>
       <type-mapping>mySQL</type-mapping>
    </metadata>
  </local-tx-datasource>
</datasources>


之后把EJB项目打包成JAR,直接放到JBOSS的server\default\deploy目录下,观察JBOSS控制台,是否正常载入JAR,是否正常绑定我们自己定义的那些JNDI服务。

后面就是测试了,属于展现层的东西,我是单独做一个项目,之后把上面的JAR在导入新PATH中,包括把JBOSS中client目录的所有JAR也要导入PATH。

import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.openstarbbs.user.service.IUserBean;
 
public class Test
{
    public static void main(String[] args)
    {
        try
        {
            InitialContext ctx = new InitialContext();
        
            IUserBean iuserBean = (IUserBean)ctx.lookup("UserBean/remote");
            System.out.println(iuserBean.getUser().getName());
            
        }
        catch(NamingException ne)
        {
            ne.printStackTrace();
        }
    }
}


OK,JAVA控制台输出:laoyang

成功。
  • 大小: 38 KB
分享到:
评论
2 楼 junzilan0929cn 2011-08-31  

学习了.
1 楼 xiaowur 2010-05-20  
写的很详细...
对我很有帮助

相关推荐

    ejb3 带源码

    "ejb3 带源码"的资源,如"Mastering EJB3"和"Beginning EJB3 Application Development"等,提供了深入学习和实践EJB3技术的宝贵材料。 1. **EJB3核心概念**: - **实体Bean(Entity Bean)**:代表数据库中的持久...

    实战角度比较EJB2和EJB3的架构异同

    【实战角度比较EJB2和EJB3的架构异同】 EJB,即Enterprise JavaBeans,是Java EE(企业版Java)平台的核心组件之一,用于构建可复用、分布式的服务器端应用程序。EJB2和EJB3是EJB技术的两个主要版本,它们在架构上...

    EJB3最新学习教程,适合初学者

    ### EJB3 最新学习教程知识点详解 #### 一、EJB3 概念与特点 **企业级JavaBean(EJB)**是Java平台的一部分,用于开发和管理基于组件的企业应用程序。EJB3(Enterprise JavaBeans 3)是EJB规范的一个版本,它大大...

    EJB3 PPT教程

    这个PPT教程详细介绍了EJB3的各种核心概念和技术,旨在帮助学习者掌握EJB3的核心特性并能实际应用到项目开发中。** **一、SessionBean** SessionBean是EJB中的一个关键组件,它代表了业务逻辑,通常处理单个客户端...

    EJB3的三本好书第3本 Mastering EJB3 4ed

    EJB3的三本好书之三,也很不错的一本ejb3的书籍,是英文版,附带源代码,这本书的好处是与Mastering EJB 3ed有一定的继承性,可以对比来看. 3本书的地址 1. Beginning EJB3 Application Development From Novice to ...

    EJB3基础教程

    EJB3是2006年发布的,相较于早期版本,它降低了学习曲线,引入了注解驱动的开发,消除了XML配置文件的需求,从而提高了开发效率。 ### 2. EJB3组件类型 EJB3包括三种主要组件: - **会话bean(Session Beans)**...

    EJB3入门例子

    通过学习和运行这些示例,开发者可以更好地理解和掌握EJB3的核心概念和技术。 在实际开发中,理解并熟练运用EJB3的注解、持久化、依赖注入和会话bean机制,能有效提升Java EE应用的开发效率和质量。同时,选择合适...

    ejb3进阶案例

    **ejb3进阶案例详解** ejb3(Enterprise JavaBeans 3.0)是Java EE平台中的核心组件之一,它极大地简化了企业级...通过深入学习和实践这些案例,开发者能够更好地掌握ejb3的精髓,从而构建出高效、稳定的企业级应用。

    EJB3应用实例

    **EJB3应用实例** EJB(Enterprise JavaBeans)3是Java EE(Enterprise Edition)平台中的核心组件之一,主要用于构建可扩展、可移植且高度模块化的企业级应用程序。EJB3引入了许多重大改进,简化了开发流程,降低...

    EJB3开发Entity

    EJB3是EJB规范的一个重要版本,它在EJB2的基础上进行了许多简化和改进,使得开发更加高效且易于理解。本文将深入探讨EJB3中的Entity Bean,它是EJB3中的持久化组件,用于代表数据库中的实体。 1. **实体Bean的概念*...

    EJB 3实战 带书签

    EJB(Enterprise JavaBeans)3是Java平台企业版(Java EE)的一个核心组件,用于简化大型企业级应用的开发。自从EJB 3版本推出以来,它在简化实体管理、依赖注入和声明式服务等方面有了重大改进,使得开发者可以更加...

    ejb3-persistence

    【ejb3-persistence】是Java企业版(Enterprise JavaBeans,EJB)3.0规范中的持久化模块,它是Java后端开发中的一个重要组件,主要处理数据库操作和对象关系映射(Object-Relational Mapping,ORM)。在Spring框架中...

    EJB3(入门经典简版)

    **企业级JavaBeans(EJB)3.0详解** 企业级JavaBeans(EJB)是...通过学习EJB3,开发者能够构建出高效、稳定的企业级应用。阅读《EJB3(入门经典的简版)》这本书,将帮助你深入理解这一关键的技术,并掌握其实际应用。

    EJB3的三本好书第2本, EJB3 in Action 2007

    EJB3的三本好书第二本,最好的介绍ejb3的书,看过之后,其他的书都送人了,而且附带的源代码,几乎包括了所有的主流应用服务器的例子,glassfish, jboss, weblogic, oracleAS 3本书分别是: 1. Beginning EJB3 ...

    EJB3 入门经典 源码

    这个压缩包文件"**EJB3 入门经典 源码**"很可能是为了帮助初学者理解并学习EJB3的基本概念、设计模式和实际应用。 EJB3的主要特点包括: 1. **注解驱动(Annotation-Based)**:EJB3引入了注解,使得开发者无需...

    ejb3_structs

    【 ejb3_structs 】是一个关于企业级...这个项目对于学习EJB3和Struts的集成,以及理解企业级Java应用开发有很好的实践价值。通过深入研究源码,可以更好地掌握这两者之间的协作方式,从而提升在实际开发中的能力。

    EJB3实战的源代码

    EJB3是EJB规范的一个重要版本,它在EJB2的基础上进行了重大改进,极大地简化了开发流程,降低了学习曲线,提升了开发效率。 在"EJB3实战的源代码"这个资源中,我们可以深入学习和理解EJB3的各种特性。EJB3引入了...

    EJB3 实例练习(一)

    EJB3是EJB规范的一个重要版本,它在EJB2的基础上进行了许多简化和改进,使得开发更加高效且易于理解。在这个实例练习中,我们将探讨EJB3的基本概念、特性以及如何创建和运行一个简单的EJB3应用。 1. EJB3概述 EJB3...

    EJB3入门

    在学习EJB3时,阅读《EJB3.pdf》这份文档将帮助你理解这些核心概念,并通过实践例子加深理解。同时,结合源码分析和使用相关工具,如IDEA中的EJB插件,可以更好地掌握EJB3的开发技巧。记得实践是检验真理的唯一标准...

    Weblogic11g+EJB3的小例子

    在这个"Weblogic11g+EJB3的小例子"中,我们可以看到以下几个关键知识点: 1. **EJB3核心概念**: - **实体Bean(Entity Bean)**:代表业务数据模型,通常与数据库中的表进行映射。EJB3引入了JPA(Java ...

Global site tag (gtag.js) - Google Analytics