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.lang.reflect.InvocationTargetException;
025: import java.sql.SQLException;
026: import java.sql.PreparedStatement;
027: import java.sql.Connection;
028: import java.sql.Statement;
029: import java.sql.ResultSet;
030:
031: import javax.ejb.EJBException;
032:
033: import org.jboss.deployment.DeploymentException;
034: import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCCMPFieldBridge;
035: import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCFieldBridge;
036: import org.jboss.ejb.EntityEnterpriseContext;
037:
038: /**
039: * Base class for create commands where the PK value is generated as side
040: * effect of performing the insert operation. This is typically associated
041: * with database platforms that use identity columns
042: *
043: * @author <a href="mailto:jeremy@boynes.com">Jeremy Boynes</a>
044: */
045: public abstract class JDBCIdentityColumnCreateCommand extends
046: JDBCAbstractCreateCommand {
047: protected JDBCCMPFieldBridge pkField;
048: protected String pkSQL;
049:
050: protected boolean isInsertField(JDBCFieldBridge field) {
051: // do not include PK fields in the insert
052: return super .isInsertField(field)
053: && !field.isPrimaryKeyMember();
054: }
055:
056: protected void initGeneratedFields() throws DeploymentException {
057: super .initGeneratedFields();
058: pkField = getGeneratedPKField();
059: }
060:
061: protected int executeInsert(int paramIndex, PreparedStatement ps,
062: EntityEnterpriseContext ctx) throws SQLException {
063: int rows = ps.executeUpdate();
064: Connection c;
065: Statement s = null;
066: ResultSet rs = null;
067: try {
068: c = ps.getConnection();
069: s = c.createStatement();
070: rs = s.executeQuery(pkSQL);
071: if (!rs.next()) {
072: throw new EJBException("ResultSet was empty");
073: }
074: pkField.loadInstanceResults(rs, 1, ctx);
075: } catch (RuntimeException e) {
076: throw e;
077: } catch (Exception e) {
078: // throw EJBException to force a rollback as the row has been inserted
079: throw new EJBException("Error extracting generated key", e);
080: } finally {
081: JDBCUtil.safeClose(rs);
082: JDBCUtil.safeClose(s);
083: }
084: return rows;
085: }
086:
087: /**
088: * Helper for subclasses that use reflection to avoid driver dependencies.
089: * @param t an Exception raised by a reflected call
090: * @return SQLException extracted from the Throwable
091: */
092: protected SQLException processException(Throwable t) {
093: if (t instanceof InvocationTargetException) {
094: t = ((InvocationTargetException) t).getTargetException();
095: }
096: if (t instanceof SQLException) {
097: return (SQLException) t;
098: }
099: if (t instanceof RuntimeException) {
100: throw (RuntimeException) t;
101: }
102: if (t instanceof Error) {
103: throw (Error) t;
104: }
105: log.error(t);
106: throw new IllegalStateException();
107: }
108: }
|