001: package net.sourceforge.jaxor;
002:
003: import net.sourceforge.jaxor.api.EntityInterface;
004: import net.sourceforge.jaxor.api.FieldAdapter;
005: import net.sourceforge.jaxor.api.LifeCycleListener;
006: import net.sourceforge.jaxor.util.NullProxy;
007: import net.sourceforge.jaxor.util.SystemException;
008:
009: import java.io.Serializable;
010: import java.sql.Connection;
011: import java.sql.PreparedStatement;
012: import java.sql.SQLException;
013: import java.util.Iterator;
014: import java.util.List;
015:
016: public class SqlAdapter implements Serializable {
017:
018: private final MetaRow _meta;
019: private final EntityRow _row;
020: private final EntityWrapper _entity;
021:
022: public SqlAdapter(EntityInterface entity) {
023: this (entity.getMetaRow(), entity.getFields(), entity);
024: }
025:
026: public SqlAdapter(MetaRow row, EntityRow ent, EntityInterface inter) {
027: _meta = row;
028: _row = ent;
029: if (inter instanceof LifeCycleListener)
030: _entity = new EntityWrapper(inter,
031: (LifeCycleListener) inter);
032: else
033: _entity = new EntityWrapper(inter,
034: (LifeCycleListener) NullProxy
035: .create(LifeCycleListener.class));
036: if (_meta == null)
037: throw new NullPointerException(
038: "MetaRow is null. Cannot persist entity without metarow. Please set MetaRow on Entity");
039: }
040:
041: public String insertSQL() {
042: return _meta.getParser().getInsert();
043: }
044:
045: public String updateSQL() {
046: return _meta.getParser().getUpdate();
047: }
048:
049: public String deleteSQL() {
050: return _meta.getParser().getDelete();
051: }
052:
053: public void addToInsertBatch(PreparedStatement stmt)
054: throws SQLException {
055: List all = _meta.getInsertColumns();
056: int count = 1;
057: for (Iterator iter = all.iterator(); iter.hasNext(); count++) {
058: MetaField element = (MetaField) iter.next();
059: FieldAdapter field = _row.getField(element.getColumn());
060: field.addToStatement(stmt, count);
061: }
062: }
063:
064: private void registerLoad() {
065: _entity.Entity.registerLoad();
066: }
067:
068: public PreparedStatement getInsertPreparedStatement(Connection conn)
069: throws SQLException {
070: PreparedStatement stmt = conn.prepareStatement(insertSQL());
071: boolean success = false;
072: try {
073: addToInsertBatch(stmt);
074: success = true;
075: return stmt;
076: } finally {
077: if (!success) {
078: try {
079: stmt.close();
080: } catch (SQLException e) {
081: e.printStackTrace();
082: }
083: }
084: }
085: }
086:
087: public void insert(Connection conn) {
088: PreparedStatement stmt = null;
089: try {
090: stmt = getInsertPreparedStatement(conn);
091: stmt.execute();
092: } catch (SQLException exc) {
093: throw new SystemSQLException(exc, _meta, conn);
094: } finally {
095: if (stmt != null) {
096: try {
097: stmt.close();
098: } catch (SQLException e) {
099: e.printStackTrace();
100: }
101: }
102: }
103: }
104:
105: public void addToDeleteBatch(PreparedStatement stmt)
106: throws SQLException {
107: List _pik = _meta.getPrimaryKey();
108: int count = 1;
109: for (Iterator iter = _pik.iterator(); iter.hasNext(); count++) {
110: MetaField element = (MetaField) iter.next();
111: _row.getField(element.getColumn()).addToStatement(stmt,
112: count);
113: }
114: }
115:
116: public void beforeInsert() {
117: _entity.Cycle.beforeInsert();
118: _row.notifyFieldsOfInsert(_entity.Entity.getJaxorContext());
119: validate();
120: }
121:
122: public void afterInsert() {
123: _entity.Cycle.afterInsert();
124: registerLoad();
125: }
126:
127: public void beforeUpdate() {
128: _entity.Entity.unregister();
129: _entity.Cycle.beforeUpdate();
130: _row.notifyFieldsOfUpdate(_entity.Entity.getJaxorContext());
131: validate();
132: }
133:
134: public void afterUpdate() {
135: registerLoad();
136: _entity.Cycle.afterUpdate();
137: }
138:
139: public void beforeDelete() {
140: _entity.Cycle.beforeDelete();
141: _row.notifyFieldsOfDelete(_entity.Entity.getJaxorContext());
142: }
143:
144: public void afterDelete() {
145: getEntity().getJaxorContext().getCache().remove(getEntity());
146: }
147:
148: public void delete(Connection conn) {
149: int rows = executeDeletion(conn);
150: if (rows == 0) {
151: throw new EntityNotFoundException();
152: }
153: if (rows > 1)
154: throw new SystemSQLException("Primary key is not unique");
155: }
156:
157: private int executeDeletion(Connection conn) {
158: PreparedStatement stmt = null;
159: try {
160: stmt = getDeletePreparedStatement(conn);
161: return stmt.executeUpdate();
162: } catch (SQLException exc) {
163: throw new SystemSQLException(exc, _meta, conn);
164: } finally {
165: if (stmt != null) {
166: try {
167: stmt.close();
168: } catch (SQLException e) {
169: e.printStackTrace();
170: }
171: }
172: }
173: }
174:
175: public PreparedStatement getDeletePreparedStatement(Connection conn)
176: throws SQLException {
177: PreparedStatement stmt = conn.prepareStatement(deleteSQL());
178: addToDeleteBatch(stmt);
179: return stmt;
180: }
181:
182: public void update(Connection conn) {
183: PreparedStatement stmt = createStatement(conn);
184: try {
185: List matchedObjects = _row.getUpdateMatchValues();
186: List update = _meta.getUpdateColumns();
187: int count = 1;
188: for (Iterator iter = update.iterator(); iter.hasNext(); count++) {
189: MetaField element = (MetaField) iter.next();
190: _row.getField(element.getColumn()).addToStatement(stmt,
191: count);
192: }
193:
194: for (Iterator iter = matchedObjects.iterator(); iter
195: .hasNext(); count++) {
196: MatchUpdate element = (MatchUpdate) iter.next();
197: element.update(stmt, count);
198: }
199: int rows = stmt.executeUpdate();
200: processUpdates(rows, _entity.Entity);
201: } catch (SQLException exc) {
202: throw new SystemSQLException(exc, _entity.Entity);
203: } finally {
204: try {
205: stmt.close();
206: } catch (SQLException e) {
207: e.printStackTrace();
208: }
209: }
210: }
211:
212: private PreparedStatement createStatement(Connection conn) {
213: try {
214: return conn.prepareStatement(updateSQL());
215: } catch (SQLException e) {
216: throw new SystemException(e);
217: }
218: }
219:
220: private void validate() {
221: _entity.Entity.validate();
222: }
223:
224: private EntityInterface getEntity() {
225: return _entity.Entity;
226: }
227:
228: protected void processUpdates(int numberOfUpdates,
229: EntityInterface entity) {
230: if (numberOfUpdates != 1)
231: throw new ConcurrencyException(
232: "Every update should update 1 and only 1 row, not "
233: + numberOfUpdates, entity);
234: }
235:
236: public static class MatchUpdate implements Serializable {
237: public Object value;
238: public FieldAdapter mapper;
239:
240: public void update(PreparedStatement stmt, int param)
241: throws SQLException {
242: mapper.addToStatement(stmt, param, value);
243: }
244: }
245:
246: private static class EntityWrapper implements Serializable {
247: public final EntityInterface Entity;
248: public final LifeCycleListener Cycle;
249:
250: public EntityWrapper(EntityInterface entity,
251: LifeCycleListener life) {
252: Entity = entity;
253: Cycle = life;
254: }
255: }
256: }
|