Ted Husted wrote:
> Now, the next step is to create a RowSet from scratch to insert a new
> record to a new table. Given this, there doesn't seem to be any reason
> to have a seperate value object bean for a data set that is coming from
> or going to a persistent store.

In case anyone is interested, all I did was select a record that wasn't
there (primary key=0), and, bingo-bango, CachedRowSet created an empty
but valid RowSet, ready to receive new rows. 

So, now instead of duplicating the data in my own set of properties, I'm
using the CachedRowSet's storage locations directly through a thin
wrapper with conventional mutators and accessors. This reduces the
overhead of redundant storage, retains all the flexibility of a standard
value object, is compatible with existing code bases, and can also
leverage the type casting built into RowSets. 

[ DBMS ] -> [ RowSet ] -> [ ActionForm -> RowSet ] -> 
[ DBMS ] -> [ RowSet ] -> [ JSP or ActionForm ]

And, of course, a RowSet can be treated just like a ResultSet in a JSP,
but without the overhead of an open connection.

A full treatment will follow, but here are some snippets.

ResultValue.java 
// a RowSet Iterator wrapper subclassed as a 
// value object wrapper around a CachedRowSet (whew!)

     /**
      * Return the account
      */
     public String getAccount() {
         try {
             return values.getString("account");
         }
         catch (SQLException sqle) {
             return null;
         }
     }

// .. more property wrappers

     /**
      * Bulk mutator for data transfer from another object
      */
    public void set(
            String bid, String lot, String amount, String account,
            String precedence, String  bidType, String bidFrom, String
pickup
        ) throws SQLException {

         values.updateString("bid_key",bid);
         values.updateString("lot",lot);
         values.updateString("amount",amount);
         values.updateString("account",account);
         values.updateString("bidder_key",precedence);
         values.updateString("bidType",bidType);
         values.updateString("bidFrom",bidFrom);
         values.updateString("pickup",pickup);
    }

     /**
      * Convenience constructor to set internal RowSet
      */
    public ResultValue(RowSet values) {
        super(values);
    }

Result.java 
// encapsulates instance of ResultValue with other 
// helper properties and serves as a data access object

    public int insert() throws SQLException {

        ResultValue resultValue = (ResultValue) getRows();

          // MySQL can't insert via a RowSet, so use a Statement instead
        return Statements.bidInsert(
            resultValue.getLot(),
            resultValue.getAmount(),
            resultValue.getAccount(),
            resultValue.getPrecedence(),
            resultValue.getBidType(),
            resultValue.getBidFrom(),
            resultValue.getPickup()
       );
    }


Access.java (an Action)
// selects appropriate classes and 
// methods for given request task

        // -- INSERT --
        if (task.equals("insert")) {

                // Instantiate blank RowSet
                result = thisResult.select(); // key=0
                resultValue =
                        (ResultValue) thisResult.getRows();

                // Create new row in empty set
                resultValue.moveToInsertRow(); 

                // Transfer data
                resultValue.set(
                   thisForm.getBid(),
                   thisForm.getLot(),
                   thisForm.getAmount(),
                   thisForm.getAccount(),
                   thisForm.getPrecedence(),
                   thisForm.getBidType(),
                   thisForm.getBidFrom(),
                   thisForm.getPickup()
                );

                // Execute insert command for this Result object
                result = thisResult.insert();

                // Analyze outcome
                if (result==0) {
                        message = "error.database.error";
                }
                else {
                        message = "record.inserted";
                }
        }

When retrieving multiple rows, the Result object (a proper JavaBean) can
be inserted in the request, along with it's RowSet. I wrote a quick
Iterator wrapper for RowSets so it could be used by the iterate tag. 

Front to back This gives you a pattern like:

// Search.perform

                // Select command
                if (task.equals("lot"))
                    command = Commands.BID_SEARCH_LOT;
                if (task.equals("account"))
                    command = Commands.BID_SEARCH_ACCOUNT;

                // Ready result
                Result thisResult = new Result(key,task,command);

                // Retrieve data set
                thisResult.execute();

                // Queue for view
                request.setAttribute("result",thisResult);

// Result.execute

    public void execute() throws SQLException {
        rows = new ResultValue(
            RowSets.getRows( getKey(),getCommand() )
        );

    }

// RowSets.getRows

    public static final RowSet getRows(String key, String command)
throws SQLException {
       RowSet crs = new CachedRowSet();
       crs.setDataSourceName(Commands.JNDI_NAME_KEY);
       crs.setCommand(command);
       crs.setString(1,key);
       crs.setMaxRows(Setup.MAX_ROWS);
       crs.execute();
       return crs;
    }

// result.jsp 

<logic:iterate name="result" property="rows" id="row">

    <td align="left">
      <html:link page="/bid/Access.do?task=select" paramName="row"
paramId="key" paramProperty="bid">
        <bean:write name="row" property="bid" filter="true"/>
      </html:link> 
    </td>
    <td align="left">
        <bean:write name="row" property="lot" filter="true"/>
    </td>
    <td align="left">
        <bean:write name="row" property="amount" filter="true"/>
    </td>
    <td align="left">
      <html:link page="/account/Access.do?task=select" paramName="row"
paramId="key" paramProperty="account">
        <bean:write name="row" property="username" filter="true"/>
      </html:link> 
    </td>
    <td align="left">
        <bean:write name="row" property="bidType" filter="true"/>
    </td>
    <td align="left">
        <bean:write name="row" property="bidFrom" filter="true"/>
    </td>
    <td align="left">
        <bean:write name="row" property="pickup" filter="true"/>
    </td>
  </tr>
</logic:iterate>

Again, I'll update Strut by Strut with a full treatment of this, with
working stub files.

-- Ted Husted, Husted dot Com, Fairport NY USA.
-- Custom Software ~ Technical Services.
-- Tel 716 737-3463.
-- http://www.husted.com/about/struts/

Reply via email to