使用WebsharpDAO实现O/R Mapping和持久层

时间:2021-07-15 15:43:16

1.         WebsharpDAO能够做什么

WebsharpDAO封装了对象同数据库之间的交互,可以方便的执行一些常用的数据库和对象交互的任务。
WebsharpDAO是一个非常简单的框架,他的目的不是设计一个如JDO、Hibernate一样的完整的解决方案,而是设计一个可用的方案,能够解决开发过程中的一般问题。他比JDO和Hibernate简单很多,使用也方便很多。在接口设计上,也参考了JDO的标准,或者,可以把他看成一个JDO的一个Mini版本。

可以从以下网址下载全部源代码和示例工程:

http://www.uml.org.cn/opensource/websharp/

 

2.         主要接口

PersistenceManager接口,操纵对象同数据库进行交互的主要接口:

public interface PersistenceManager

{

     void close() throws SQLException;

     boolean isClosed() throws SQLException;

     Transaction currentTransaction();

 

     void persistNewObject(PersistenceCapable pc) throws SQLException;

     void updateObject(PersistenceCapable pc) throws SQLException;

     void deleteObject(PersistenceCapable pc) throws SQLException;

     void reload(PersistenceCapable pc) throws SQLException;

 

     PersistenceCapable findObjectByPrimaryKey(Object id, PersistenceCapable pc) throws SQLException;

 

     Query newQuery();

     Query newQuery(Class entityType);

     Query newQuery(Class entityType, String filter);

     Query newQuery(Class entityType,String filter,ArrayList paramColletion);

 

     Connection getConnection();

}

Transaction接口,操纵事务处理:

public interface Transaction

{

     void begin() throws SQLException;

     void commit() throws SQLException;

     void rollback() throws SQLException;

     PersistenceManager getPersistenceManager();

}

Query接口,查询对象:

public interface Query

{

     Class getEntityType();

     void setEntityType(Class entityType);

     String getFilter();

     void setFilter(String filter);

   

     ArrayList getParameters();

     void setParameters(ArrayList array);

     void addParameter(Object param);

     String getOrdering();

     void setOrdering(String ordering);

     public boolean IgnoreCache=true;

     PersistenceCapable[] queryObject() throws SQLException;

     PersistenceManager getPersistenceManager();

 

     boolean isClosed();

     void close ();

     SqlOperator getSqlOperator();

     void setSqlOperator(SqlOperator conn);

}

 

SqlOperator接口,封装了一些常用的数据库操纵功能:

public interface SqlOperator

{

     ResultSet executeQuery(String sql) throws SQLException;

     ResultSet executeQuery(String sql,ArrayList parameters) throws SQLException;

     RowSet executeRowSet(String sql) throws SQLException;

     RowSet executeRowSet(String sql,ArrayList parameters) throws SQLException;

     int executeUpdate(String sql) throws SQLException;

     int executeUpdate(String sql,ArrayList parameters) throws SQLException;

     void close() throws SQLException;

     boolean isClosed() throws SQLException;

     Connection getConnection();

}

 

PersistenceCapable接口,所有的实体类都必须实现这个接口:

public interface PersistenceCapable

{

     public String[] getFields();   //字段列表

     public String[] getKeyFields();  //关键字

     public String getTableName();   //对应的表名

}

 

 

3.         实体类的编写规范:

a)       为了方便实现,实体类同数据库表是一一对应的。

b)       所有的实体类都必须实现PersistenceCapable接口。例如,Product类可以表示如下:

public class Product implements PersistenceCapable

{

     public Product()

     {

         super();

     }

     public String[] getFields()

     {

         return new

String[]{"ProductID" ,"Name" ,"UnitName" ,"Description" ,"Price" ,"CurrentCount" };

     }

 

public String[] getKeyFields()

     {

         return new String[]{"PRODUCTID"};

     }

     public String getTableName()

     {

         return "Product";

     }

    

     private String productID = "";

     public String getProductID()

     {

         return productID;

     }

     public void setProductID(String productID)

     {

         this.productID = productID;

     }

    

     private String name = "";

     public String getName()

     {

         return name;

     }

     public void setName(String name)

     {

         this.name = name;

     }

    

     private String unitName = "";

     public String getUnitName()

     {

         return unitName;

     }

     public void setUnitName(String unitName)

     {

         this.unitName = unitName;

     }

    

     private String description = "";

     public String getDescription()

     {

         return description;

     }

     public void setDescription(String description)

     {

         this.description = description;

     }

    

     private double price = 0;

     public double getPrice()

     {

         return price;

     }

     public void setPrice(double price)

     {

         this.price = price;

     }

    

     private double currentCount = 0;

     public double getCurrentCount()

     {

         return currentCount;

     }

     public void setCurrentCount(double currentCount)

     {

         this.currentCount = currentCount;

     }

    

}

 

 

c)        属性必须同字段一一对应。例如,有一个ProductName字段,则必须有相应的getset方法,注意getset方法的大小写和getFields()方法中的大小写一致。

 

4.         使用PersistenceManager存取对象

使用PersistenceManager存取对象的过程是:

1)  实例化一个PersistenceManager对象。要实例化一个PersistenceManager对象,请通过PersistenceManagerFactorycreatePersistenceManager方法。下面是一个例子:

PersistenceManager pm = null;

        try

        {

               pm = PersistenceManagerFactory.instance().createPersistenceManager();

               ……;

}

2)  实例化一个实体对象:

Product  p = new Product();

p.ProductID = …….

3)  调用PersistenceManager相应的方法:

pm.persistNewObject(p);

或者:

pm.updateObject(dept);

或者

pm.deleteObject(dept);

4)  关闭PersistenceManager

pm.close();

下面是一个完整的例子:

ProductForm productForm = (ProductForm)form;

Product p = new Product();

p.setProductID(productForm.getProductID());

p.setName(productForm.getName());

p.setUnitName(productForm.getUnitName());

p.setPrice(productForm.getPrice().doubleValue());

p.setCurrentCount(productForm.getCurrentCount().doubleValue());

p.setDescription(productForm.getDescription());

try

{

     PersistenceManager pm = 

                       PersistenceManagerFactory.instance().createPersistenceManager();

     pm.persistNewObject(p);

     pm.close();

}

catch (Exception e)

{

     errors.add("name", new ActionError("id"));

}

 

5.         使用事务处理

事务处理通过Transaction接口来进行。

try

{

     PersistenceManager pm = 

                       PersistenceManagerFactory.instance().createPersistenceManager();

     Transaction trans = pm.currentTransaction();

     trans.begin();

     pm.persistNewObject(p);

     trans.commit();

}

catch (Exception e)

{

     trans.rollback();

}

finally

{

     pm.close();

}

 

6.         进行对象的查询

查询对象可以通过两种方式进行:

1)  根据主关键字查询单个对象

可以通过PersistenceManagerfindObjectByPrimaryKey方法来进行。下面是一个例子:

         DEPT dept = new DEPT();

         PersistenceManager pm = null;

         try

         {

              pm = PersistenceManagerFactory.instance().createPersistenceManager();

              pm.findObjectByPrimaryKey(new Integer(90), dept);

              pm.close();

              System.out.println(dept.getDEPTNO());

              System.out.println(dept.getDNAME());

              System.out.println(dept.getLOC());

         }

         catch (Exception e)

         {

              System.out.println(e.toString());

         }

 

2)  根据条件查询一组对象

可以通过Query接口来完成这个功能。下面是一个例子:

         PersistenceManager pm = null;

         try

         {

              pm = PersistenceManagerFactory.instance().createPersistenceManager();

              Query q = pm.newQuery(DEPT.class);

              q. setFilter(DEPTNO > 10);

              PersistenceCapable[] depts = q.queryObject();

              for(int i=0;i<depts.length;i++)

              {

                   System.out.print(i);

                   System.out.print("/t");

                   System.out.print(((DEPT)depts[i]).getDEPTNO());

                   System.out.print("/t");

                   System.out.print(((DEPT)depts[i]).getDNAME());

                   System.out.print("/t");

                   System.out.println(((DEPT)depts[i]).getLOC());

              }

         }

         catch (Exception e)

         {

              System.out.println(e.toString());

         }

      

7.         数据库连接的获取

有些时候,我们也需要直接使用数据库连接来进行一些对数据库的操作。在一个项目中,应该总是通过ConnectionFactory来获取一个连接。

可以使用如下语句获取一个默认的数据库连接:

Connection conn = ConnectionFactory.getConnection()

也可以通过指明一个DataSource名称来获取一个特定的连接:

Connection conn = ConnectionFactory.getConnection(dataSourceName)

获取连接后,你可以象使用通常的数据库连接一样使用得到的连接。

Connection连接的一些参数,必须在ApplicationResources.properties文件中设置。其格式是:

db_fromdatasource=false                     是否使用DataSource

db_datasourcename=                         DataSource的名称

db_url=jdbc:oracle:thin:@newtest            数据库连接的URL

db_driver=oracle.jdbc.driver.OracleDriver   JDBC驱动程序

db_user=user                                数据库用户名

db_password=pwd                             数据库密码

 

 

8.         SqlOperator的使用

也可以通过ConnectionFactory获取一个SqlOperatorSqlOperator的定义见前面的内容。下面是两种获取的方法:

SqlOperator operator = ConnectionFactory. getSqlOperator()

SqlOperator operator = ConnectionFactory. getSqlOperator(dataSourceName)

下面通过SqlOperator执行一个查询,返回一个ResultSet

String sql = SELECT * FROM Product WHERE Price > ? ;

ArrayList parameters = new ArrayList(1);

parameters.add(100);

SqlOperator operator = ConnectionFactory.getSqlOperator()

ResultSet rst = operator.executeQuery(sql, params);

……

operator.close();

也可以通过SqlOperator返回一个RowSet。返回RowSet的使用方法同ResultSet一样。

RowSetResultSet一样,也是一个数据集,只不过它是可以断开连接,并且可以前后滚动的数据集。当在层之间传输数据集的时候,请尽量使用RowSet,这样,我们就可以在业务逻辑层得到一个数据集,然后马上断开数据库连接,然后把数据集传递到界面层。

关于SqlOperator的其他方法,请参考前面的接口说明。

9.         Tomcat数据库连接池的配置

首先,在项目的web.xml文件中添加一个名为“Websharp/DataSourceName”的环境变量,指明使用的DataSource的名称。格式如下:

<web-app>

……

     <env-entry>

         <env-entry-name>org/websharp/dao/DataSourceName</env-entry-name>

         <env-entry-value>jdbc/newtest</env-entry-value>

         <env-entry-type>java.lang.String</env-entry-type>

     </env-entry>

</web-app>

然后,在TomcatServer.xml文件中添加相应的连接池设置:

<Context docBase="daotest" path="/daotest" reloadable="true" source="com.ibm.etools.webtools.server:daotest">

     <Resource auth="SERVLET" name="jdbc/newtest" type="javax.sql.DataSource"/>

     <ResourceParams name="jdbc/newtest">

         <parameter>

              <name>factory</name>

              <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>

         </parameter>

         <parameter><name>username</name><value>scott</value></parameter>

         <parameter><name>password</name><value>tiger</value></parameter>

         <parameter><name>driverClassName</name>

                   <value>oracle.jdbc.driver.OracleDriver</value>

         </parameter>

         <parameter><name>url</name>

                   <value>jdbc:oracle:thin:@newtest </value>

         </parameter>

         <parameter><name>maxActive</name><value>20</value></parameter>

         <parameter><name>maxIdle</name><value>10</value></parameter>

         <parameter><name>maxWait</name><value>-1</value></parameter>

     </ResourceParams>

</Context>

 

进行如上配置后,就可以使用ConnectionFactorygetConnection方法正确的从连接池中获取数据库连接了。