KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > triactive > jdo > store > OracleBlobMapping


1 /*
2  * Copyright 2004 (C) TJDO.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the TJDO License version 1.0.
6  * See the terms of the TJDO License in the documentation provided with this software.
7  *
8  * $Id: OracleBlobMapping.java,v 1.3 2004/03/30 06:15:56 jackknifebarber Exp $
9  */

10 package com.triactive.jdo.store;
11
12 import com.triactive.jdo.PersistenceManager;
13 import com.triactive.jdo.StateManager;
14 import java.io.InputStream JavaDoc;
15 import java.io.OutputStream JavaDoc;
16 import java.io.IOException JavaDoc;
17 import java.sql.Connection JavaDoc;
18 import java.sql.PreparedStatement JavaDoc;
19 import java.sql.ResultSet JavaDoc;
20 import java.sql.SQLException JavaDoc;
21 import java.sql.Types JavaDoc;
22 import javax.jdo.JDODataStoreException;
23 import javax.jdo.JDOFatalInternalException;
24 import oracle.sql.BLOB;
25 import org.apache.log4j.Category;
26
27
28 public class OracleBlobMapping extends ByteArrayMapping implements PostInsertProcessing, PostUpdateProcessing
29 {
30     private static final Category LOG = Category.getInstance(OracleBlobMapping.class);
31
32     private final ClassBaseTable table;
33     private ColumnMapping idMapping = null;
34     private String JavaDoc fetchStmt = null;
35     private String JavaDoc updateStmt = null;
36
37
38     public OracleBlobMapping(DatabaseAdapter dba, Class JavaDoc type)
39     {
40         super(dba, type);
41
42         this.table = null;
43     }
44
45
46     public OracleBlobMapping(Column col)
47     {
48         super(col);
49
50         this.table = null;
51     }
52
53
54     public OracleBlobMapping(ClassBaseTable table, int relativeFieldNumber)
55     {
56         super(table.newColumn(relativeFieldNumber));
57
58         col.setUnlimitedLength();
59
60         this.table = table;
61     }
62
63
64     private synchronized void initialize()
65     {
66         if (idMapping == null)
67         {
68             if (table == null)
69                 throw new JDOFatalInternalException("Not mapped to class base table: " + this);
70
71             idMapping = table.getIDMapping();
72
73             FetchStatement stmt = new FetchStatement(table);
74             stmt.select(getColumn());
75             stmt.andCondition(stmt.referenceColumn(idMapping.getColumn()) + " = ?");
76
77             fetchStmt = stmt.toString() + " FOR UPDATE";
78
79             updateStmt = "UPDATE " + table.getName() + " SET " + col.getName() + " = NULL WHERE " + idMapping.getColumn().getName() + " = ?";
80                 
81         }
82     }
83
84
85     protected TypeInfo getTypeInfo()
86     {
87         return dba.getTypeInfo(Types.BLOB);
88     }
89
90
91     public String JavaDoc getSQLInsertionValue()
92     {
93         return "EMPTY_BLOB()";
94     }
95
96
97     public String JavaDoc getSQLUpdateValue()
98     {
99         return "EMPTY_BLOB()";
100     }
101
102
103     public void setObject(PersistenceManager pm, PreparedStatement JavaDoc ps, int param, Object JavaDoc value)
104     {
105         // No-op. Statement text includes "EMPTY_BLOB()" instead of "?"
106
}
107
108
109     public Object JavaDoc getObject(PersistenceManager pm, ResultSet JavaDoc rs, int param)
110     {
111         byte[] value = null;
112
113         try
114         {
115             BLOB blob = (BLOB)rs.getBlob(param);
116
117             if (!rs.wasNull() && blob != null)
118             {
119                 int len = (int)Math.min(blob.length(), Integer.MAX_VALUE);
120                 value = new byte[len];
121
122                 try
123                 {
124                     InputStream JavaDoc in = blob.getBinaryStream();
125
126                     try
127                     {
128                         int off = 0;
129
130                         while (off < len)
131                         {
132                             int n = in.read(value, off, len - off);
133
134                             if (n < 0)
135                                 throw new SQLException JavaDoc("Premature end-of-BLOB, expected " + len + ", got " + off);
136
137                             off += n;
138                         }
139                     }
140                     finally
141                     {
142                         in.close();
143                     }
144                 }
145                 catch (IOException JavaDoc e)
146                 {
147                     throw new JDODataStoreException("Error reading Oracle BLOB object: param = " + param, e);
148                 }
149             }
150         }
151         catch (SQLException JavaDoc e)
152         {
153             throw dba.newDataStoreException("Can't get byte[] result: param = " + param, e);
154         }
155
156         return value;
157     }
158
159
160     public void postInsert(StateManager sm, Connection JavaDoc conn, Object JavaDoc value)
161     {
162         postUpdate(sm, conn, value);
163     }
164
165
166     /**
167      * Retrieve the empty BLOB locator created by the insert statement
168      * and write out the current BLOB field value to the Oracle BLOB object
169      */

170     public void postUpdate(StateManager sm, Connection JavaDoc conn, Object JavaDoc value)
171     {
172         initialize();
173
174         byte[] ba = (byte[])value;
175
176         /*
177          * Need to do this more efficiently, but it's going to take a refactor
178          * of the way the whole getSQLInsertionValue()/getSQLUpdateValue()
179          * stuff works.
180          */

181         if (ba == null)
182             updateAsNull(sm, conn);
183         else
184             updateWithValue(sm, conn, ba);
185     }
186
187
188     private void updateAsNull(StateManager sm, Connection JavaDoc conn)
189     {
190         PersistenceManager pm = sm.getPersistenceManager();
191
192         try
193         {
194             PreparedStatement JavaDoc ps = conn.prepareStatement(updateStmt);
195
196             try
197             {
198                 Object JavaDoc id = sm.getObjectId();
199                 idMapping.setObject(pm, ps, 1, id);
200
201                 long startTime = System.currentTimeMillis();
202
203                 ps.executeUpdate();
204
205                 if (LOG.isDebugEnabled())
206                     LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + updateStmt);
207             }
208             finally
209             {
210                 ps.close();
211             }
212         }
213         catch (SQLException JavaDoc e)
214         {
215             throw dba.newDataStoreException("BLOB update failed: " + updateStmt, e);
216         }
217     }
218
219
220     private void updateWithValue(StateManager sm, Connection JavaDoc conn, byte[] value)
221     {
222         PersistenceManager pm = sm.getPersistenceManager();
223
224         try
225         {
226             PreparedStatement JavaDoc ps = conn.prepareStatement(fetchStmt);
227
228             try
229             {
230                 Object JavaDoc id = sm.getObjectId();
231                 idMapping.setObject(pm, ps, 1, id);
232
233                 long startTime = System.currentTimeMillis();
234
235                 ResultSet JavaDoc rs = ps.executeQuery();
236
237                 try
238                 {
239                     if (LOG.isDebugEnabled())
240                         LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + fetchStmt);
241
242                     if (!rs.next())
243                         throw new ObjectNotFoundException("No such database row", sm.getObject());
244
245                     BLOB blob = (BLOB)rs.getBlob(1);
246
247                     try
248                     {
249                         OutputStream JavaDoc out = blob.getBinaryOutputStream();
250
251                         try
252                         {
253                             out.write(value);
254                         }
255                         finally
256                         {
257                             out.close();
258                         }
259                     }
260                     catch (IOException JavaDoc e)
261                     {
262                         throw new JDODataStoreException("Error writing Oracle BLOB object", e);
263                     }
264                 }
265                 finally
266                 {
267                     rs.close();
268                 }
269             }
270             finally
271             {
272                 ps.close();
273             }
274         }
275         catch (SQLException JavaDoc e)
276         {
277             throw dba.newDataStoreException("BLOB update failed: " + fetchStmt, e);
278         }
279     }
280 }
281
Popular Tags