As far as I know, there's no way to make iBATIS do this natively. You could
use your existing resultMaps and a QueryWithRowDelegate() and, in your row
delegate, add Stock objects to a Dictionary as you encounter them. Then,
manually assign the Stock object (pulling the object reference from your
Dictionary) and replace the duplicate one that iBATIS created.

E.g., something like (just pseudocode, thinking out loud in this e-mail) the
following. You'd have to watch out for synchronization issues, though. And
you might need to check and see if your "cached" version in the dictionary
is out of date as compared to what's coming out of the database. 

public class PositionDao
{

        // This will hold the instances of Stock objects, keyed by their
ticker symbols
        private Dictionary<string, Stock> mTickerToStocksMap =
                new Dictionary<string, Stock>();

        public IList<Position> GetAllPositions()
        {
                return
LocalSqlMap.QueryWithRowDelegate<Position>("Position.GetAllPositions", null,
                        delegate(object obj, object parameter,
IList<Position> positions)
                        {
                                Position pos;
                                Stock stk;
                        
                                pos = (Position)obj;

                                // Do we already have a stock object with
this ticker created? If not,
                                // use the one that iBATIS made for us and
store it
                                if
(!mTickerToStocksMap.TryGetValue(pos.Stock.Ticker, out stk))
                                {
        
mTickerToStocksMap.Add(pos.Stock.Ticker, pos.Stock);
                                }
                                else
                                {
                                        // Let's replace the one iBATIS made
with the one we have
                                        // cached in our dictionary
                                        // TODO: Is our version out of date?
If so, update it
                                        pos.Stock = stk;
                                }

                                // Add the position to the list that will
get returned
                                positions.Add(pos);
                        });
        }
        
}

If there is an easier way, I'm curious to know the answer, too. Good luck!

V/R,
Nicholas Piasecki

-----Original Message-----
From: Clyde Coolidge [mailto:[EMAIL PROTECTED] 
Sent: Saturday, November 10, 2007 2:13 PM
To: [email protected]
Subject: Question About Complex Types

Firstly, thanks for such a great product.  I just started using
iBatis.NET, but already feel in love with its power and simplicity.

That being said, after studying your documentation sections on complex
types, solving the N+1 issue, etc., I am still having troubleb
understanding how to deal with the following issue.

Suppose my program only has two classes, Stock and Position.

class Stock
{
 public string ticker;
 public string price;
}

class Position
{
 public Stock stock;
 public double quantity;
}

Also assume there are two database tables which can be used to
populate the above.

CREATE TABLE Stock (ticker varchar, price float)
CREATE TABLE Position (ticker varchar, quantity int)

My approach thus far has been to use the following result maps and
statement.

<resultMap id="Stock_Result" class="MyApp.Stock">
 <result property="ticker" column="ticker" />
 <result property="price" column="price" />
</resultMap>

<resultMap id="Position_Result" class="MyApp.Position">
 <result property="stock" resultMapping="Stock_Result" />
 <result property="quantity" column="quantity" />
</resultMap>

<statements>
 <select id="GetPositions" resultMap="Position_Result">
   SELECT p.ticker, p.quantity, s.price
   FROM Position p
   JOIN Stock s ON p.ticker = s.ticker
 </select>
</statements>

If I call method QueryForList with this statement, things seem to work
fine.  I get back a list of Position objects, each containing a
fully-formed Stock object.

My problem is that each Stock object is obviously independent.  If I
have multiple positions in say, IBM, I will have duplicate Stock
objects.  I am looking for a way to create all of the Position objects
(each containing a reference to a Stock object), but only create new
Stock objects when a new ticker is encountered.  In other words, if I
have two positions in IBM, I want to have them both point to the same
Stock object.

Is there any way to accomplish this using iBatis.NET?  I've looked at
groupby, but can't seem to make it work this way.  Any help or advice
is greatly appreciated!

- Clyde

Reply via email to