1 10 package com.triactive.jdo.store; 11 12 import com.triactive.jdo.PersistenceManager; 13 import com.triactive.jdo.StateManager; 14 import java.io.InputStream ; 15 import java.io.OutputStream ; 16 import java.io.IOException ; 17 import java.sql.Connection ; 18 import java.sql.PreparedStatement ; 19 import java.sql.ResultSet ; 20 import java.sql.SQLException ; 21 import java.sql.Types ; 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 fetchStmt = null; 35 private String updateStmt = null; 36 37 38 public OracleBlobMapping(DatabaseAdapter dba, Class 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 getSQLInsertionValue() 92 { 93 return "EMPTY_BLOB()"; 94 } 95 96 97 public String getSQLUpdateValue() 98 { 99 return "EMPTY_BLOB()"; 100 } 101 102 103 public void setObject(PersistenceManager pm, PreparedStatement ps, int param, Object value) 104 { 105 } 107 108 109 public Object getObject(PersistenceManager pm, ResultSet 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 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 ("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 e) 146 { 147 throw new JDODataStoreException("Error reading Oracle BLOB object: param = " + param, e); 148 } 149 } 150 } 151 catch (SQLException 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 conn, Object value) 161 { 162 postUpdate(sm, conn, value); 163 } 164 165 166 170 public void postUpdate(StateManager sm, Connection conn, Object value) 171 { 172 initialize(); 173 174 byte[] ba = (byte[])value; 175 176 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 conn) 189 { 190 PersistenceManager pm = sm.getPersistenceManager(); 191 192 try 193 { 194 PreparedStatement ps = conn.prepareStatement(updateStmt); 195 196 try 197 { 198 Object 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 e) 214 { 215 throw dba.newDataStoreException("BLOB update failed: " + updateStmt, e); 216 } 217 } 218 219 220 private void updateWithValue(StateManager sm, Connection conn, byte[] value) 221 { 222 PersistenceManager pm = sm.getPersistenceManager(); 223 224 try 225 { 226 PreparedStatement ps = conn.prepareStatement(fetchStmt); 227 228 try 229 { 230 Object id = sm.getObjectId(); 231 idMapping.setObject(pm, ps, 1, id); 232 233 long startTime = System.currentTimeMillis(); 234 235 ResultSet 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 out = blob.getBinaryOutputStream(); 250 251 try 252 { 253 out.write(value); 254 } 255 finally 256 { 257 out.close(); 258 } 259 } 260 catch (IOException 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 e) 276 { 277 throw dba.newDataStoreException("BLOB update failed: " + fetchStmt, e); 278 } 279 } 280 } 281 | Popular Tags |