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的朋友开个头,少走点弯路。

[img]http://dl.iteye.com/upload/attachment/172922/5eeeb9aa-7ec1-302e-be30-e641a2eda2d4.jpg[/img]

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


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

成功。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值