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.jdbc2;
023:
024: import org.jboss.ejb.EntityEnterpriseContext;
025: import org.jboss.ejb.plugins.cmp.jdbc2.bridge.JDBCEntityBridge2;
026: import org.jboss.ejb.plugins.cmp.jdbc2.bridge.JDBCCMPFieldBridge2;
027: import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCEntityCommandMetaData;
028: import org.jboss.ejb.plugins.cmp.jdbc.JDBCUtil;
029: import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCFieldBridge;
030: import org.jboss.logging.Logger;
031: import org.jboss.deployment.DeploymentException;
032:
033: import javax.ejb.CreateException;
034: import javax.ejb.DuplicateKeyException;
035: import java.lang.reflect.Method;
036: import java.sql.SQLException;
037: import java.sql.Connection;
038: import java.sql.ResultSet;
039: import java.sql.PreparedStatement;
040:
041: /**
042: * @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a>
043: * @version <tt>$Revision: 57209 $</tt>
044: */
045: public class PkSqlCreateCommand implements CreateCommand {
046: private Logger log;
047: private JDBCEntityBridge2 entityBridge;
048: private String pkSql;
049: private JDBCCMPFieldBridge2 pkField;
050:
051: public void init(JDBCStoreManager2 manager)
052: throws DeploymentException {
053: this .entityBridge = (JDBCEntityBridge2) manager
054: .getEntityBridge();
055: log = Logger.getLogger(getClass().getName() + "."
056: + entityBridge.getEntityName());
057:
058: final JDBCFieldBridge[] pkFields = entityBridge
059: .getPrimaryKeyFields();
060: if (pkFields.length > 1) {
061: throw new DeploymentException(
062: "This entity-command cannot be used with composite primary keys!");
063: }
064: this .pkField = (JDBCCMPFieldBridge2) pkFields[0];
065:
066: JDBCEntityCommandMetaData metadata = entityBridge.getMetaData()
067: .getEntityCommand();
068: pkSql = metadata.getAttribute("pk-sql");
069: if (pkSql == null) {
070: throw new DeploymentException(
071: "pk-sql attribute must be set for entity "
072: + entityBridge.getEntityName());
073: }
074: if (log.isDebugEnabled()) {
075: log.debug("entity-command generate pk sql: " + pkSql);
076: }
077: }
078:
079: public Object execute(Method m, Object[] args,
080: EntityEnterpriseContext ctx) throws CreateException {
081: Object pk;
082: PersistentContext pctx = (PersistentContext) ctx
083: .getPersistenceContext();
084: if (ctx.getId() == null) {
085: Connection con = null;
086: PreparedStatement ps = null;
087: ResultSet rs = null;
088: try {
089: if (log.isDebugEnabled()) {
090: log.debug("executing sql: " + pkSql);
091: }
092:
093: con = entityBridge.getDataSource().getConnection();
094: ps = con.prepareStatement(pkSql);
095: rs = ps.executeQuery();
096:
097: if (!rs.next()) {
098: throw new CreateException("pk-sql " + pkSql
099: + " returned no results!");
100: }
101:
102: pk = pkField.loadArgumentResults(rs, 1);
103: pctx.setFieldValue(pkField.getRowIndex(), pk);
104: pk = entityBridge.extractPrimaryKeyFromInstance(ctx);
105: } catch (SQLException e) {
106: log.error("Failed to execute pk sql. error code: "
107: + e.getErrorCode() + ", sql state: "
108: + e.getSQLState(), e);
109: throw new CreateException("Failed to execute pk sql: "
110: + e.getMessage() + ", error code: "
111: + e.getErrorCode() + ", sql state: "
112: + e.getSQLState());
113: } finally {
114: JDBCUtil.safeClose(rs);
115: JDBCUtil.safeClose(ps);
116: JDBCUtil.safeClose(con);
117: }
118:
119: if (pk == null) {
120: log.error("Primary key for created instance is null.");
121: throw new CreateException(
122: "Primary key for created instance is null.");
123: }
124:
125: pctx.setPk(pk);
126: } else {
127: // insert-after-ejb-post-create
128: try {
129: pctx.flush();
130: } catch (SQLException e) {
131: if ("23000".equals(e.getSQLState())) {
132: throw new DuplicateKeyException(
133: "Unique key violation or invalid foreign key value: pk="
134: + ctx.getId());
135: } else {
136: throw new CreateException(
137: "Failed to create instance: pk="
138: + ctx.getId() + ", state="
139: + e.getSQLState() + ", msg="
140: + e.getMessage());
141: }
142: }
143: pk = ctx.getId();
144: }
145: return pk;
146: }
147: }
|