上篇文章我写了一个关于WASCE+EJB2.1的简单Demo,只是为了搭建如何使用EJB2.1的环境,但是,实际开发中一定会用到数据库,那么今天,我继续介绍一下如何在企业级项目中利用WASCE配置一个数据源,继而如果在SessionBean中调用的例子。首先,我们简单设计一个数据库wasce,创建一个users表,字段包括id,name,sex,age。具体创建语句如下:
--
-- Create schema wasce
--
CREATE DATABASE IF NOT EXISTS wasce;
USE wasce;
--
-- Definition of table `users`
--
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL auto_increment,
`name` varchar(45) NOT NULL,
`sex` varchar(45) NOT NULL,
`age` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `users`
--
/*!40000 ALTER TABLE `users` DISABLE KEYS */;
INSERT INTO `users` (`id`,`name`,`sex`,`age`) VALUES
(1,'zf','male','29'),
(2,'zz','female','30');
然后启动WASCE服务,访问http://localhost:8888/console/portal/Welcome,(8888端口是我自己修改的,默认是8080)。默认用户名system密码manager。登陆管理界面,按照我在《关于eclipse+wasce+mysql的环境搭建》中的方式,搭建一个数据源 wasce。准备完成后,进行程序开发,我们需要在HelloEJB中添加三个类,一个数据库工具类DBUtils,提供对数据源的查找和创建数据库链接;一个数据库操作类DBAdaptor,对具体表进行CURD操做;一个数据实体类Users,存放对应表数据。具体代码如下:
DBUtils类
/**
* 数据库工具类
* @author Frank
* @version 1.0
*
*/
public class DBUtils {
private static DataSource ds = null;
private static Context initCtx = null;
private static final Logger logger = Logger.getLogger("DBUtils");
protected Connection conn;
protected ResultSet resultSet;
protected PreparedStatement preparedStatement;
static {
new DBUtils();
}
public DBUtils() {
try {
Hashtable<String, String> environment = new Hashtable<String,String>();
// retrieve the initial context in order to look up the datasource
initCtx = new InitialContext(environment);
ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/wasce");
}
catch (NamingException nx) {
logger.severe(nx.toString());
}
catch (Exception e) {
logger.severe("Exception occured"+e);
}
}
public static Connection getConnectionNoIsolation() throws SQLException {
return ds.getConnection();
}
public static Connection getDefaultConnection() throws SQLException {
Connection conn = ds.getConnection();
return conn;
}
public static Connection getConnection() throws SQLException {
Connection conn = ds.getConnection();
logger.info("***open conn: " + conn);
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
return conn;
}
public static Connection getConnection(int isolationLevel) throws SQLException {
Connection conn = ds.getConnection();
if(isolationLevel < 0)
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
else
conn.setTransactionIsolation(isolationLevel);
return conn;
}
public static void closeConnection(Connection connection) throws SQLException {
closeConnection(null, connection, null);
}
public static void closeResultSet(ResultSet resultSet) throws SQLException {
closeConnection(null, null, resultSet);
}
public static void closePreparedStatement(
PreparedStatement preparedStatement) throws SQLException {
closeConnection(preparedStatement, null, null);
}
public static void closeConnection(PreparedStatement preparedStatement,
Connection conn, ResultSet resultSet) throws SQLException {
logger.info("***close conn: " + conn);
if (resultSet != null) {
resultSet.close();
}
if (preparedStatement != null) {
preparedStatement.close();
}
if (conn != null) {
conn.close();
}
}
public static void closeConnection(Statement stmt,
Connection conn, ResultSet resultSet) throws SQLException {
logger.info("***close conn: " + conn);
if (resultSet != null) {
resultSet.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
}
public static void closeConnection(CallableStatement callableStatement,
Connection conn, ResultSet resultSet) throws SQLException {
logger.info("***close conn: " + conn);
if (resultSet != null) {
resultSet.close();
}
if (callableStatement != null) {
callableStatement.close();
}
if (conn != null) {
conn.close();
}
}
}
DBAdaptor类
/**
* 数据库操作类
* @author Frank
* @version 1.0
*
*/
public class DBAdaptor extends DBUtils{
/**
* 查询所有用户对象
* @return List 用户集合
*/
public List<Users> getAllUsers() {
List<Users> list = new ArrayList<Users>() ;
Users user;
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
String sql = "select * from users;";
try {
connection = getDefaultConnection();
ps = connection.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next()) {
user = new Users();
user.setId(rs.getInt(1));
user.setName(rs.getString(2));
user.setSex(rs.getString(3));
user.setAge(rs.getString(4));
list.add(user);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
closeConnection(ps, connection, rs);
} catch (SQLException e) {
e.printStackTrace();
}
}
return list;
}
}
Users类
/**
* 数据库实体对象类
* @author Frank
* @version 1.0
*
*/
public class Users implements Serializable{
/**
* 必须进行序列化才能进行远程传输
*/
private static final long serialVersionUID = -4328059278106469334L;
private int id;
private String name;
private String sex;
private String age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
这样,基本编码准备工作已经完成,接下来,我们在HelloBean中,添加一个查询方法,代码如下:
public List<Users> getAllUsers(){
DBAdaptor dbAdaptor = new DBAdaptor();
return dbAdaptor.getAllUsers();
}
然后,在Hello和HelloLocal中添加相对应的接口,代码分别如下:
Hello类
public List<Users> getAllUsers() throws java.rmi.RemoteException;
HelloLocal类
public List<Users> getAllUsers();
到此基本代码编写完成,为了能够在客户端访问,复制一个Users类到HelloEJBClient相应目录。
接下来进行的就是如果编写配置文件和部署计划文件,要不程序也跑不起来。首先,我们需要配置HelloEAR中的geronimo-application.xml,部署计划文件,内容如下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <app:application xmlns:app="http://geronimo.apache.org/xml/ns/j2ee/application-2.0" xmlns:client="http://geronimo.apache.org/xml/ns/j2ee/application-client-2.0" xmlns:conn="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2" xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2" xmlns:ejb="http://openejb.apache.org/xml/ns/openejb-jar-2.2" xmlns:log="http://geronimo.apache.org/xml/ns/loginconfig-2.0" xmlns:name="http://geronimo.apache.org/xml/ns/naming-1.2" xmlns:pers="http://java.sun.com/xml/ns/persistence" xmlns:pkgen="http://openejb.apache.org/xml/ns/pkgen-2.1" xmlns:sec="http://geronimo.apache.org/xml/ns/security-2.0" xmlns:web="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1" application-name="HelloEAR"> <dep:environment> <dep:moduleId> <dep:groupId>default</dep:groupId> <dep:artifactId>HelloEAR</dep:artifactId> <dep:version>1.0</dep:version> <dep:type>car</dep:type> </dep:moduleId> <dep:dependencies> <dep:dependency> <dep:groupId>console.dbpool</dep:groupId> <dep:artifactId>wasce</dep:artifactId> </dep:dependency> </dep:dependencies> </dep:environment> </app:application>
其中console.dbpool是数据源组的名称,而wasce是我们要访问的数据源名。然后,我要在HelloEJB中首先配置ejb-jar.xml文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <ejb-jar id="ejb-jar_1" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd" version="2.1"> <description><![CDATA[HelloEJB generated by eclipse wtp xdoclet extension.]]></description> <display-name>HelloEJB</display-name> <enterprise-beans> <!-- Session Beans --> <session id="Session_Hello"> <description><![CDATA[An EJB named Hello]]></description> <display-name>Hello</display-name> <ejb-name>Hello</ejb-name> <home>com.ibm.demo.HelloHome</home> <remote>com.ibm.demo.Hello</remote> <local-home>com.ibm.demo.HelloLocalHome</local-home> <local>com.ibm.demo.HelloLocal</local> <ejb-class>com.ibm.demo.HelloSession</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> <resource-ref> <res-ref-name>jdbc/wasce</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> <res-sharing-scope>Shareable</res-sharing-scope> </resource-ref> </session> </enterprise-beans> <assembly-descriptor id="AssemblyDescriptor_1"> </assembly-descriptor> <ejb-client-jar>HelloEJBClient.jar</ejb-client-jar> </ejb-jar>
其中大部分都是已经生成的不需更改,只需要添加<resource-ref></resource-ref>中部分即可,jdbc/wasce是数据源的JNDI名称,我们方式时需要用到的。然后,要在HelloEJB中配置部署计划文件openejb-jar.xml,因为系统没有为我们自动创建,所以,你必须自己添加一个,内容如下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <ejb:openejb-jar xmlns:app="http://geronimo.apache.org/xml/ns/j2ee/application-2.0" xmlns:client="http://geronimo.apache.org/xml/ns/j2ee/application-client-2.0" xmlns:conn="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2" xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2" xmlns:ejb="http://openejb.apache.org/xml/ns/openejb-jar-2.2:ejb:name" xmlns:log="http://geronimo.apache.org/xml/ns/loginconfig-2.0" xmlns:name="http://geronimo.apache.org/xml/ns/naming-1.2" xmlns:pers="http://java.sun.com/xml/ns/persistence" xmlns:pkgen="http://openejb.apache.org/xml/ns/pkgen-2.1" xmlns:sec="http://geronimo.apache.org/xml/ns/security-2.0" xmlns:web="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1"> <dep:environment> <dep:moduleId> <dep:groupId>default</dep:groupId> <dep:artifactId>HelloEJB</dep:artifactId> <dep:version>1.0</dep:version> <dep:type>car</dep:type> </dep:moduleId> </dep:environment> <ejb:enterprise-beans> <ejb:session> <name:resource-ref> <name:ref-name>jdbc/wasce</name:ref-name> <name:resource-link>wasce</name:resource-link> </name:resource-ref> </ejb:session> </ejb:enterprise-beans> </ejb:openejb-jar>
其中需要我们修改的就是<ejb:entreprise-beans></ejb:enterprise-beans>中的内容,wasce是EJB要引用的数据源资源的配置名称,必须和 geronimo-application.xml的<dep:artifactId></dep:artifactId>中的名称一致,这个是一个非常重要的,也是一步很容出错的一步,我在刚开始配置这块时费了一番周折才弄清楚此处的需要添加部署计划文件,特此提醒大家一下,以免再遭周折。至此,所有配置完成,下面我们剩下最后一步,在HelloWAR中添加一个users.jsp页面显示查询的数据结果,代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="com.ibm.demo.Hello" %>
<%@ page import="com.ibm.demo.HelloLocal" %>
<%@ page import="com.ibm.demo.HelloUtil" %>
<%@ page import="java.util.List" %>
<%@ page import="com.ibm.demo.Users" %>
<%@ page import="javax.naming.NamingException" %>
<%@ page import="javax.ejb.CreateException" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Users列表</title>
<link rel="stylesheet" href="css/table.css" type="text/css" >
</head>
<body>
<%
try {
long begin1 = System.currentTimeMillis();
Hello hello = HelloUtil.getHome().create();
List<Users> list = hello.getAllUsers();
%>
<table class="mytable">
<tr>
<td class="mytable" style="background-color: #99CCFF">id</td>
<td class="mytable" style="background-color: #99CCFF">name</td>
<td class="mytable" style="background-color: #99CCFF">sex</td>
<td class="mytable" style="background-color: #99CCFF">age</td>
</tr>
<%
for(int i = 0 ; i <list.size(); i++){
Users user = list.get(i);
%>
<tr>
<td class="mytable"><%=user.getId() %></td>
<td class="mytable"><%=user.getName()%></td>
<td class="mytable"><%=user.getSex() %></td>
<td class="mytable"><%=user.getAge()%></td>
</tr>
<%
}
%>
</table>
<%
long end1 = System.currentTimeMillis();
%>
<%="远程调用花费时间:"+(end1 - begin1)+ "ms"%>
<%
long begin2 = System.currentTimeMillis();
HelloLocal helloLocal = HelloUtil.getLocalHome().create();
List<Users> list1 = helloLocal.getAllUsers();
%>
<table class="mytable">
<tr>
<td class="mytable" style="background-color: #99CCFF">id</td>
<td class="mytable" style="background-color: #99CCFF">name</td>
<td class="mytable" style="background-color: #99CCFF">sex</td>
<td class="mytable" style="background-color: #99CCFF">age</td>
</tr>
<%
for(int i = 0 ; i <list1.size(); i++){
Users user = list1.get(i);
%>
<tr>
<td class="mytable"><%=user.getId() %></td>
<td class="mytable"><%=user.getName()%></td>
<td class="mytable"><%=user.getSex() %></td>
<td class="mytable"><%=user.getAge()%></td>
</tr>
<%
}
%>
</table>
<%
long end2 = System.currentTimeMillis();
%>
<%="本地调用花费时间:"+(end2 - begin2)+ "ms"%>
<%
} catch (CreateException e) {
e.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
}
%>
</body>
</html>
启动WASCE,访问http://localhost:8888/HelloWAR/users.jsp,看到结果如图1所示。
(图1)
我们再次发现远程访问的效率远远低于本地访问。