在Beehive PageFlow Tutorial中有过一些关于Beehive Data control的介绍,这里将通过一个例子,具体说明如何运用Beehive build-in的数据控制机制来完成数据库的相关操作。
1. 首先,需要对数据库连接进行配置。
Beehive内置的数据库是derby。如果你希望使用其他数据库,就需要修改一些源码,该文件位于BEEHIVE_HOME\samples\controls-db\src\dbControl\下面。在文件DatabaseControlImpl.jcs中可以重新设置数据库的URL,例如要使用SQL Server 就可以做如下修改:
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
也可以按需求修改其他源文件。然后利用Ant工具重新编译并打包成dbControl.jar,放到web应用的相应位置(一般为WEB-INF\lib下面)即可。
2. 定义数据库操作。
我们需要创建一个jcx文件来定义所需的数据库相关操作,下面通过一个例子来说明如何完成该操作。
圆圈代表action,方块代表page
在该例中,我们在首页点击相应链接跳转到displaydata.jsp,在这里将数据库操作的结果展示出来。因此show action是核心,由它进行一系列的数据库操作并将结果输出给下个页面。Beehive使用自己的机制封装了数据库操作的具体实现,因此在show方法中,相关的代码量很少。这个例子中我们需要创建如下文件:
l Project_home\WEB-INF\src\dbcontroller\ MyFirstDBControl.jcx
l Project_home\WEB-INF\src\forms\Employee.java
l Project_home\Controller.jpf
l Project_home\*.jsp
注意:src目录下面可以根据自己的需要建立包结构,与import相对应就可以。
MyFirstDBControl.jcx
package dbcontroller;
import java.sql.SQLException;
import java.io.Serializable;
import java.util.Iterator;
import java.util.HashMap;
import javax.sql.RowSet;
import org.apache.beehive.controls.api.bean.ControlExtension;
import dbControl.DatabaseControl;
import dbControl.DatabaseControl.ConnectionDataSource;
import dbControl.DatabaseControl.SQL;
import forms.Employee;
@ControlExtension
@ConnectionDataSource(jndiName="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=Test;user=sa;password=sa")
//配置数据库连接属性
public interface MyFirstDBControl extends DatabaseControl
{
@SQL(statement="CREATE TABLE Employee (id INT PRIMARY KEY NOT NULL, " +
"name VARCHAR(50), age INT)")
public void createTable() throws SQLException;
@SQL(statement="DROP TABLE Employee")
public void dropTable() throws SQLException;
@SQL(statement="INSERT INTO Employee " + "(id, name, age) " +
"VALUES ({u.id}, {u.name}, {u.age})")
public void insertEmployee(Employee u) throws SQLException;
@SQL(statement="UPDATE Employee SET age = {age} WHERE id = {id}")
public void changeTitle(int id, String title) throws SQLException;
@SQL(statement="DELETE FROM Employee WHERE id = {id}")
public void deleteEmployee(int id) throws SQLException;
@SQL(statement="SELECT name FROM Employee")
public String[] selectAllName() throws SQLException;
@SQL(statement="SELECT * FROM Employee WHERE id={id}")
public Employee selectEmployee(int id) throws SQLException;
@SQL(statement="SELECT * FROM Employee ORDER BY id")
public Employee[] selectEmployees() throws SQLException;
@SQL(statement="SELECT * FROM Employee ORDER BY id", iteratorElementType=Employee.class)
public Iterator selectEmployeesWithIterator() throws SQLException;
@SQL(statement="SELECT * FROM Employee ORDER BY id")
public HashMap selectEmployeeWithHashMap() throws SQLException;
@SQL(statement="SELECT * FROM Employee ORDER BY id", maxRows=1)
public Employee[] selectOneEmployee() throws SQLException;
@SQL(statement="select count(*) from Employee")
public Integer getCount() throws SQLException; //返回int型的一定要定义返回类型为Integer
}
MyFirstDBControl首先定义了数据库连接的JNDI属性,接口主体则定义了能够完成的数据库操作。注意要引入相应的数据库表的持久类,即操作对象。这里分别定义了建表,删表,以及对记录的增删查改操作。对于查询,可以定义不同的返回类型以符合需求。还可以在@SQL里增加maxRows属性,控制返回的记录个数。
Employee是这个例子中用到的数据表,它有三个字段,id、name和age。我们需要创建该表对应的持久类forms\Employee.java,注意到beehive需要将该类的成员变量声明为public的。
Employee.java
package forms;
public class Employee {
public Integer id;
public String name;
public int age;
public Employee(Integer id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public Employee(Integer id) {
this.id = id;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
}
3. 在Controller中调用数据库操作。
有了上面两个文件的支持,我们就可以编辑page Flow里的核心文件Controller.jpf了。
Controller.jpf
import javax.servlet.http.HttpSession;
import org.apache.beehive.netui.pageflow.Forward;
import org.apache.beehive.netui.pageflow.PageFlowController;
import org.apache.beehive.netui.pageflow.annotations.Jpf;
import forms.Employee; //应用中所需的持久类
import dbcontroller.MyFirstDBControl; //应用中所需的数据库操作的定义文件
import org.apache.beehive.controls.api.bean.Control; //用来解释@Control,将MyFirstDBControl接口实现成bean,并完成实例化工作。
@Control
public MyFirstDBControl myControl;
public Employee u;
@Jpf.Action(
forwards={
@Jpf.Forward(name="success", path="index.jsp")
}
)
protected Forward begin()
{
return new Forward("success");
}
@Jpf.Action(
forwards={
@Jpf.Forward(name="success", path="displaydata.jsp")
}
)
protected Forward show() throws java.sql.SQLException{
u = myControl.selectEmployee(1);
getRequest().setAttribute("data",u);
return new Forward(“success”);
}
可以看到,在show方法中我们调用了selectEmployee方法,查询id为1的用户,返回值为Employee类型。然后将结果赋给一个request的变量,在页面中便可以使用该变量引用查询结果,如下所示:
<p>Name:<netui:span value="${requestScope.data.name}"/>
<p>Age:<netui:span value="${requestScope.data.age}"/>
这里,查询结果是一条记录,返回类型为对应的持久类。如果是多条记录,我们可以用Vector来作为查询结果的容器,并将之传给页面显示。代码如下:
…………..
@Control
public MyFirstDBControl myControl;
public Vector u;
…………..
protected Forward show() throws java.sql.SQLException{
u = new Vector();
Employee[] es = myControl.selectEmployees();
for(int i=0;i<es.length;i++) {
u.add(es[i]);
}
return new Forward(“success”);
}
相应地,页面也需要做些修改来展示多条记录。可以直接使用Beehive提供的标签<netui-data:repeater>,它专门用于显示以集合形式存储的数据,可以是数组,或者Vector等。
displaydata.jsp
<netui-data:repeater dataSource="pageFlow.u">
<netui-data:repeaterHeader>
<table border="1">
<tr>
<td><b>id</b></td>
<td><b>name</b></td>
<td><b>age</b></td>
</tr>
</netui-data:repeaterHeader>
<netui-data:repeaterItem>
<tr>
<td>
<netui:label value="${container.item.id}" />
</td>
<td>
<netui:label value="${container.item.name}" />
</td>
<td>
<netui:label value="${container.item.age}" />
</td>
</tr>
</netui-data:repeaterItem>
<netui-data:repeaterFooter>
</table>
</netui-data:repeaterFooter>
</netui-data:repeater>
displaydata页面将以表格的形式显示Employee表中所有的记录,如下图所示:
id
name
age
1
candy
23
2
nick
24
3
keller
25