001    package hirondelle.web4j.database;
002    
003    import hirondelle.web4j.model.Id;
004    import java.sql.Connection;
005    import java.util.ArrayList;
006    import java.util.Collections;
007    import java.util.List;
008    
009    /**
010     Version of {@link Db} for use in a transaction. 
011     
012     <P>The {@link Db} class uses an internal connection to execute single operations. 
013     If more than one operation needs to be performed as an atomic transaction, then 
014     this class is used instead.
015     
016     <P>This class is identical to {@link Db}, except that it uses a {@link Connection} passed
017     by the caller.
018     
019    <h3><a name="Parameters"></a>SQL Parameters</h3>
020     The parameters for SQL statements used by this class have the same behavior as defined by 
021     the <a href='Db.html#Parameters'>Db class</a>.
022    */
023    public final class DbTx {
024    
025      /**
026       <tt>SELECT</tt> operation which returns a single Model Object. 
027        
028       @param aConnection single connection shared by all operations in the transaction.
029       @param aClass class of the returned Model Object.
030       @param aSqlId identifies the underlying SQL statement.
031       @param aParams <a href="#Parameters">parameters</a> for the SQL statement.
032      */
033      public static <T> T fetch(Connection aConnection, Class<T> aClass, SqlId aSqlId, Object... aParams) throws DAOException {
034        SqlFetcher fetcher = SqlFetcher.forTx(aSqlId, aConnection, aParams);
035        ModelFromRow<T> builder = new ModelFromRow<T>(aClass);
036        return fetcher.fetchObject(builder);
037      }
038    
039      /**
040       <tt>SELECT</tt> operation which returns a single 'building block' value such as <tt>Integer</tt>, <tt>BigDecimal</tt>, and so on.
041      
042       @param aConnection single connection shared by all operations in the transaction.
043       @param aSupportedTargetClass class supported by the configured 
044       implementation of {@link ConvertColumn}.
045       @param aSqlId identifies the underlying SQL statement.
046       @param aParams <a href="#Parameters">parameters</a> for the SQL statement.
047      */
048      public static <T> T fetchValue(Connection aConnection, Class<T> aSupportedTargetClass, SqlId aSqlId, Object... aParams) throws DAOException {
049        SqlFetcher fetcher = SqlFetcher.forTx(aSqlId, aConnection, aParams);
050        ModelBuilder<T> builder = new ValueFromRow<T>(aSupportedTargetClass); 
051        return fetcher.fetchObject(builder);
052      }
053      
054      /**
055       <tt>SELECT</tt> operation which returns <tt>0..N</tt> Model Objects, one per row.  
056        
057       @param aConnection single connection shared by all operations in the transaction.
058       @param aClass class of the returned Model Objects.
059       @param aSqlId identifies the underlying SQL statement.
060       @param aParams <a href="#Parameters">parameters</a> for the SQL statement.
061       @return an unmodifiable {@link List} of Model Objects. The list may be empty.
062      */
063      public static <T> List<T> list(Connection aConnection, Class<T> aClass, SqlId aSqlId, Object... aParams) throws DAOException {
064        List<T> result = new ArrayList<T>();
065        SqlFetcher fetcher = SqlFetcher.forTx(aSqlId, aConnection, aParams);
066        ModelBuilder<T> builder = new ModelFromRow<T>(aClass);
067        fetcher.fetchObjects(builder, result);
068        return Collections.unmodifiableList(result);
069      }
070      
071      /**
072       <tt>SELECT</tt> operation which returns a <tt>List</tt> of 'building block' values such 
073       as <tt>Integer</tt>, <tt>BigDecimal</tt>, and so on.
074      
075       @param aConnection single connection shared by all operations in the transaction.
076       @param aSupportedTargetClass class supported by the configured 
077       implementation of {@link ConvertColumn}.
078       @param aSqlId identifies the underlying SQL statement.
079       @param aParams <a href="#Parameters">parameters</a> for the SQL statement.
080       @return an unmodifiable {@link List} of building block objects. The list may be empty.
081      */
082      public static <T> List<T> listValues(Connection aConnection, Class<T> aSupportedTargetClass, SqlId aSqlId, Object... aParams) throws DAOException {
083        List<T> result = new ArrayList<T>();
084        SqlFetcher fetcher = SqlFetcher.forTx(aSqlId, aConnection, aParams);
085        ModelBuilder<T> builder = new ValueFromRow<T>(aSupportedTargetClass); 
086        fetcher.fetchObjects(builder, result);
087        return Collections.unmodifiableList(result);
088      }
089      
090      /**
091       <tt>SELECT</tt> operation that returns a <tt>List</tt> of Model Objects "subsetted" to 
092       a particular range of rows.
093       
094       <P>This method is intended for paging through long listings. When the underlying 
095       <tt>SELECT</tt> returns many pages of items, the records can be "subsetted" by 
096       calling this method.
097       
098       <P>See {@link hirondelle.web4j.ui.tag.Pager}.
099       @param aConnection single connection shared by all operations in the transaction.
100       @param aClass class of the returned Model Objects.
101       @param aSqlId identifies the underlying SQL statement.
102       @param aStartIndex 1-based index indentifying the first row to be returned.
103       @param aPageSize number of records to be returned.
104       @param aParams <a href="#Parameters">parameters</a> for the SQL statement.
105       @return an unmodifiable {@link List} of Model Objects. The list may be empty.
106      */
107      public static <T> List<T> listRange(Connection aConnection, Class<T> aClass, SqlId aSqlId, Integer aStartIndex, Integer aPageSize, Object... aParams) throws DAOException  {
108        List<T> result = new ArrayList<T>();
109        SqlFetcher fetcher = SqlFetcher.forTx(aSqlId, aConnection, aParams);
110        fetcher.limitRowsToRange(aStartIndex, aPageSize);
111        ModelBuilder<T> builder = new ModelFromRow<T>(aClass); 
112        fetcher.fetchObjects(builder, result);
113        return Collections.unmodifiableList(result);
114      }
115    
116      /**
117       <tt>INSERT</tt>, <tt>UPDATE</tt>, or <tt>DELETE</tt> operations which take parameters.
118        
119       @param aConnection single connection shared by all operations in the transaction.
120       @param aSqlId identifies the underlying SQL statement.
121       @param aParams <a href="#Parameters">parameters</a> for the SQL statement.
122       @return the number of records affected by this edit operation.
123      */
124      public static int edit(Connection aConnection, SqlId aSqlId, Object... aParams) throws DAOException, DuplicateException {
125        SqlEditor change = SqlEditor.forTx(aSqlId, aConnection, aParams);
126        return change.editDatabase();
127      }
128      
129      /**
130       <tt>INSERT</tt> operation which returns the database identifier of the added record.
131      
132       <P>This operation is not supported by all databases. See 
133       {@link java.sql.Statement} for more information.
134       
135       @param aConnection single connection shared by all operations in the transaction.
136       @param aSqlId identifies the underlying SQL statement.
137       @param aParams <a href="#Parameters">parameters</a> for the SQL statement.
138      */
139      public static Id add(Connection aConnection, SqlId aSqlId, Object... aParams) throws DAOException, DuplicateException  {
140        SqlEditor add = SqlEditor.forTx(aSqlId, aConnection, aParams);
141        return new Id(add.addRecord());
142      }
143    
144      /**
145       <tt>DELETE</tt> operation which takes parameters.
146        
147       @param aConnection single connection shared by all operations in the transaction.
148       @param aSqlId identifies the underlying SQL statement.
149       @param aParams identifies the item to be deleted. Often 1 or more {@link Id} objects.
150       @return the number of deleted records.
151      */
152      public static int delete(Connection aConnection, SqlId aSqlId, Object... aParams) throws DAOException {
153        SqlEditor delete = SqlEditor.forTx(aSqlId, aConnection, aParams);
154        return delete.editDatabase();
155      }
156      
157      /**
158       <tt>SELECT</tt> operation which typically returns a single item with a <tt>0..N</tt> relation. 
159        
160       <P>The <tt>ResultSet</tt> is parsed into a single parent Model Object having a <tt>List</tt> of 
161       <tt>0..N</tt> child Model Objects. 
162       See note on <a href="#CompundObjects">compound objects</a> for more information.
163         
164       @param aConnection single connection shared by all operations in the transaction.
165       @param aClassParent class of the parent Model Object.
166       @param aClassChild class of the child Model Object.
167       @param aNumTrailingColsForChildList number of columns appearing at the end of the <tt>ResultSet</tt> which 
168       are passed to the <em>child</em> constructor.
169       @param aSqlId identifies the underlying SQL statement.
170       @param aParams <a href="#Parameters">parameters</a> to the underlying SQL statement.
171      */
172      public static <T> T fetchCompound(Connection aConnection, Class<T> aClassParent, Class<?> aClassChild, int aNumTrailingColsForChildList, SqlId aSqlId, Object... aParams) throws DAOException {
173        SqlFetcher fetcher = SqlFetcher.forTx(aSqlId, aConnection, aParams);
174        ModelBuilder<T> builder = new ModelFromRow<T>(aClassParent, aClassChild, aNumTrailingColsForChildList);
175        return fetcher.fetchObject(builder);
176      }
177    
178      /**
179       <tt>SELECT</tt> operation which typically returns mutliple items item with a <tt>0..N</tt> relation. 
180        
181       <P>The <tt>ResultSet</tt> is parsed into a <tt>List</tt> of parent Model Objects, each having <tt>0..N</tt> 
182       child Model Objects. See note on <a href="#CompundObjects">compound objects</a> for more information.
183         
184       @param aConnection single connection shared by all operations in the transaction.
185       @param aClassParent class of the parent Model Object.
186       @param aClassChild class of the child Model Object.
187       @param aNumTrailingColsForChildList number of columns appearing at the end of the <tt>ResultSet</tt> which 
188       are passed to the <em>child</em> constructor.
189       @param aSqlId identifies the underlying SQL statement.
190       @param aParams <a href="#Parameters">parameters</a> to the underlying SQL statement.
191     */
192      public static <T> List<T> listCompound(Connection aConnection, Class<T> aClassParent, Class<?> aClassChild, int aNumTrailingColsForChildList, SqlId aSqlId, Object... aParams) throws DAOException {
193        List<T> result = new ArrayList<T>();
194        SqlFetcher fetcher = SqlFetcher.forTx(aSqlId, aConnection, aParams);
195        ModelBuilder<T> builder = new ModelFromRow<T>(aClassParent, aClassChild, aNumTrailingColsForChildList);
196        fetcher.fetchObjects(builder, result);
197        return result;
198      }
199      
200      // PRIVATE 
201      
202      private DbTx() {
203        //prevent construction by the caller
204      }
205    }