001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ejb.plugins.cmp.jdbc;
023:
024: import java.sql.Connection;
025: import java.sql.PreparedStatement;
026: import java.util.Iterator;
027: import javax.ejb.EJBException;
028: import javax.sql.DataSource;
029: import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCCMPFieldBridge;
030: import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCCMRFieldBridge;
031: import org.jboss.logging.Logger;
032:
033: /**
034: * Deletes relations from a relation table.
035: *
036: * @author <a href="mailto:dain@daingroup.com">Dain Sundstrom</a>
037: * @author <a href="mailto:alex@jboss.org">Alex Loubyansky</a>
038: * @version $Revision: 57209 $
039: */
040: public final class JDBCDeleteRelationsCommand {
041: private final Logger log;
042: private int maxKeysInDelete;
043: private String maxKeysStatement;
044:
045: public JDBCDeleteRelationsCommand(JDBCStoreManager manager) {
046: // Create the Log
047: log = Logger.getLogger(this .getClass().getName() + "."
048: + manager.getMetaData().getName());
049:
050: maxKeysInDelete = manager.getJDBCTypeFactory().getTypeMapping()
051: .getMaxKeysInDelete();
052: }
053:
054: //
055: // This command needs to be changed to chunk delete commands, because
056: // some database have a limit on the number of parameters in a statement.
057: //
058: public void execute(RelationData relationData) {
059: if (relationData.removedRelations.size() == 0) {
060: return;
061: }
062:
063: Iterator pairs = relationData.removedRelations.iterator();
064: int i = 0;
065: while (i < relationData.removedRelations.size()) {
066: String sql = getSQL(relationData,
067: relationData.removedRelations.size() - i);
068:
069: Connection con = null;
070: PreparedStatement ps = null;
071: JDBCCMRFieldBridge cmrField = relationData
072: .getLeftCMRField();
073: try {
074: // create the statement
075: if (log.isDebugEnabled()) {
076: log.debug("Executing SQL: " + sql);
077: }
078:
079: // get the connection
080: DataSource dataSource = cmrField.getDataSource();
081: con = dataSource.getConnection();
082: ps = con.prepareStatement(sql);
083:
084: // set the parameters
085: setParameters(ps, relationData, pairs);
086:
087: // execute statement
088: int rowsAffected = ps.executeUpdate();
089: if (log.isDebugEnabled()) {
090: log.debug("Rows affected = " + rowsAffected);
091: }
092:
093: i += (maxKeysInDelete > 0 ? maxKeysInDelete
094: : relationData.removedRelations.size());
095: } catch (Exception e) {
096: throw new EJBException(
097: "Could not delete relations from "
098: + cmrField.getQualifiedTableName(), e);
099: } finally {
100: JDBCUtil.safeClose(ps);
101: JDBCUtil.safeClose(con);
102: }
103: }
104: }
105:
106: private String getSQL(RelationData relationData, int keys) {
107: if (maxKeysInDelete > 0 && keys >= maxKeysInDelete) {
108: if (maxKeysStatement == null) {
109: maxKeysStatement = createSQL(relationData,
110: maxKeysInDelete);
111: }
112: return maxKeysStatement;
113: }
114: return createSQL(relationData, keys);
115: }
116:
117: private static String createSQL(RelationData relationData,
118: int keysInDelete) {
119: JDBCCMRFieldBridge left = relationData.getLeftCMRField();
120: JDBCCMRFieldBridge right = relationData.getRightCMRField();
121:
122: StringBuffer sql = new StringBuffer(300);
123: sql.append(SQLUtil.DELETE_FROM).append(
124: left.getQualifiedTableName()).append(SQLUtil.WHERE);
125:
126: StringBuffer whereClause = new StringBuffer(20);
127: whereClause.append('(');
128: // left keys
129: SQLUtil.getWhereClause(left.getTableKeyFields(), whereClause)
130: .append(SQLUtil.AND);
131: // right keys
132: SQLUtil.getWhereClause(right.getTableKeyFields(), whereClause)
133: .append(')');
134: String whereClauseStr = whereClause.toString();
135: sql.append(whereClauseStr);
136: for (int i = 1; i < keysInDelete; ++i) {
137: sql.append(SQLUtil.OR).append(whereClauseStr);
138: }
139:
140: return sql.toString();
141: }
142:
143: private void setParameters(PreparedStatement ps,
144: RelationData relationData, Iterator pairs) throws Exception {
145: int index = 1;
146: JDBCCMPFieldBridge[] leftFields = (JDBCCMPFieldBridge[]) relationData
147: .getLeftCMRField().getTableKeyFields();
148: JDBCCMPFieldBridge[] rightFields = (JDBCCMPFieldBridge[]) relationData
149: .getRightCMRField().getTableKeyFields();
150: int keyIndex = 0;
151: while (pairs.hasNext()) {
152: RelationPair pair = (RelationPair) pairs.next();
153:
154: // left keys
155: Object leftId = pair.getLeftId();
156: for (int i = 0; i < leftFields.length; ++i) {
157: index = leftFields[i].setPrimaryKeyParameters(ps,
158: index, leftId);
159: }
160:
161: // right keys
162: Object rightId = pair.getRightId();
163: for (int i = 0; i < rightFields.length; ++i) {
164: index = rightFields[i].setPrimaryKeyParameters(ps,
165: index, rightId);
166: }
167:
168: if (maxKeysInDelete > 0) {
169: ++keyIndex;
170: if (keyIndex == maxKeysInDelete) {
171: break;
172: }
173: }
174: }
175: }
176: }
|