alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Glassfish example source code file (UpdateStatement.java)

This example Glassfish source code file (UpdateStatement.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Glassfish tags/keywords

columnelement, columnref, columnref, dbstatement, iterator, jdbc, localfielddesc, localfielddesc, noi18n, noi18n, object, sql, sqlexception, string, stringbuffer, stringbuffer, util

The Glassfish UpdateStatement.java source code

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

/*
 * UpdateStatement.java
 *
 * Created on October 3, 2001
  *
 */

package com.sun.jdo.spi.persistence.support.sqlstore.sql.generator;

import org.netbeans.modules.dbschema.ColumnElement;
import com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager;
import com.sun.jdo.spi.persistence.support.sqlstore.Transaction;
import com.sun.jdo.spi.persistence.support.sqlstore.database.DBVendorType;
import com.sun.jdo.spi.persistence.support.sqlstore.model.ForeignFieldDesc;
import com.sun.jdo.spi.persistence.support.sqlstore.model.LocalFieldDesc;
import com.sun.jdo.spi.persistence.support.sqlstore.sql.UpdateObjectDescImpl;
import com.sun.jdo.spi.persistence.support.sqlstore.sql.constraint.ConstraintValue;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;

/**
 * This class is used to generate update/insert/delete statements.
 */
public class UpdateStatement extends Statement implements Cloneable {

    public int minAffectedRows;

    private Map dbStatementCache = new HashMap();

    /** The UpdateQueryplan */
    UpdateQueryPlan plan;

    /** List of ColumnRef for the where clause used during batch. */
    private List columnRefsForWhereClause;

    /** List of version columns */
    private List versionColumns;

    /** Flag indicating whether we use batch. */
    private boolean batch = false;

    /** Insert values for INSERT statements. */
    private StringBuffer values;

    /** */
    private boolean isConstraintAdded;

    /** Name of the USE_BATCH property. */
    public static final String UPDATE_VERSION_COL_PROPERTY =
        "com.sun.jdo.spi.persistence.support.sqlstore.sql.generator.UPDATE_VERSION_COL"; // NOI18N

    /**
     * Property to swich on/off updating of version col.
     * Note, the default is true, meaning we try to update version col if the
     * property is not specified.
     */
    private static final boolean UPDATE_VERSION_COL = Boolean.valueOf(
        System.getProperty(UPDATE_VERSION_COL_PROPERTY, "true")).booleanValue(); // NOI18N


    public UpdateStatement(DBVendorType vendorType, UpdateQueryPlan plan, boolean batch) {
        super(vendorType);
        this.plan = plan;
        columnRefsForWhereClause = new ArrayList();
        this.batch = batch;
        minAffectedRows = 1;
    }

    public void addColumn(ColumnElement columnElement, Object value) {
        addColumnRef(new ColumnRef(columnElement, value));
    }

    /**
     * Batch helper method. Adds the columnElement to the list of
     * ColumnRefs for the where clause and then calls addConstraint.
     */
    protected void addConstraint(ColumnElement columnElement,
                                 LocalFieldDesc lf, Object value) {
        columnRefsForWhereClause.add(new ColumnRef(columnElement, value));
        addConstraint(lf, value);
    }

    /** Calculates the index of the where clause ColumnRefs */
    private void calculateWhereClauseColumnRefIndexes() {
        // calculate where clause column ref indexes
        // NOTE, the sqlstore processes the constraints in reverse order,
        // so start with the last index and decrement
        int nextIndex = columns.size() + columnRefsForWhereClause.size();
        for (Iterator i = columnRefsForWhereClause.iterator(); i.hasNext(); ) {
            ColumnRef columnRef = (ColumnRef)i.next();
            columnRef.setIndex(nextIndex--);
        }
    }

    public boolean isConstraintAdded() {
        return isConstraintAdded;
    }

    public void markConstraintAdded() {
        isConstraintAdded = true;
    }

    /** @inheritDoc */
    public QueryPlan getQueryPlan() {
         return plan;
    }

    /**
     * @inheritDoc
     */
    protected void generateStatementText() {

        statementText = new StringBuffer();

        StringBuffer columnList = generateColumnText();
        StringBuffer constraint = processConstraints();
        String tableName = ((QueryTable) tableList.get(0)).getTableDesc().getName();

        // Create the query filling in the column list, table name, etc.
        switch (action) {
            case QueryPlan.ACT_UPDATE:
                statementText.append("update ");// NOI18N
                appendQuotedText(statementText, tableName);
                statementText.append(" set ").append(columnList).append(" where ").append(constraint); // NOI18N
                break;

            case QueryPlan.ACT_DELETE:
                statementText.append("delete from ");// NOI18N
                appendQuotedText(statementText, tableName);
                statementText.append(" where ").append(constraint); // NOI18N
                break;

            case QueryPlan.ACT_INSERT:
                statementText.append("insert into ");// NOI18N
                appendQuotedText(statementText, tableName);
                statementText.append("(").append(columnList).// NOI18N
                        append(") values ").append("(").append(values).append(")"); // NOI18N
                break;
        }

        calculateWhereClauseColumnRefIndexes();
    }

    private StringBuffer generateColumnText() {
        StringBuffer columnList = new StringBuffer();
        int numValues = -1;

        for (int i = 0; i < columns.size(); i++) {
            ColumnRef c = (ColumnRef) columns.get(i);

            if (columnList.length() > 0) {
                columnList.append(", "); // NOI18N
            }
            switch (action) {
                case QueryPlan.ACT_UPDATE:
                    appendQuotedText(columnList, c.getName());
                    columnList.append("= ?"); // NOI18N
                    break;

                case QueryPlan.ACT_INSERT:
                    appendQuotedText(columnList, c.getName());
                    if (i == 0) {
                        values = new StringBuffer().append(" ?"); // NOI18N
                    } else {
                        values.append(", ?"); // NOI18N
                    }
                    break;
            }

            // Do not create an InputValue in the case of batch update.
            // Method bindInputValues will get the value using the ColumnRef.
            if (!batch &&
                ((action == QueryPlan.ACT_UPDATE) ||
                    (action == QueryPlan.ACT_INSERT))) {
                numValues = numValues + 1;
                InputValue val = new InputValue(c.getValue(), c.getColumnElement());
                inputDesc.values.add(numValues, val);
            }
        }

        appendVersionColumnUpdateClause(columnList);

        return columnList;
    }

    /**
     * Appends clause to update version column. The generated clause will be of
     * the following form
     * <code> versionColumnName = versionColumnNane + 1 
     * @param setClause Text for the set clause of update statement
     */
    private void appendVersionColumnUpdateClause(StringBuffer setClause) {
        if(UPDATE_VERSION_COL) {
            if (versionColumns != null)
            {
                for (int i = 0; i < versionColumns.size(); i++) {
                    ColumnElement columnElement = (ColumnElement) versionColumns.get(i);
                    String columnName = columnElement.getName().getName();
                    setClause.append(", ");
                    appendQuotedText(setClause, columnName);
                    setClause.append(" = ");
                    appendQuotedText(setClause, columnName);
                    setClause.append(" + ");
                    setClause.append("1");
                }
            }
        }
    }


    public void addLocalConstraints(int action, ForeignFieldDesc f, SQLStateManager sm) {
        for (int i = 0; i < f.localFields.size(); i++) {
            LocalFieldDesc lf = (LocalFieldDesc) f.localFields.get(i);

            if (action == QueryPlan.ACT_INSERT) {
                // For inserts into the join table, we get the values we are inserting
                // for the parent object and the added object.
                ColumnElement lc = (ColumnElement) f.assocLocalColumns.get(i);

                addColumn(lc, lf.getValue(sm));
            } else if (action == QueryPlan.ACT_DELETE) {
                LocalFieldDesc alf = (LocalFieldDesc) f.assocLocalFields.get(i);

                // For deletes from the join table, we get the constraint values
                // from the parent object and the remove object.
                addConstraint(alf, lf.getValue(sm));
            }
        }
    }

    public void addForeignConstraints(int action, ForeignFieldDesc f, SQLStateManager sm) {
        for (int i = 0; i < f.foreignFields.size(); i++) {
            LocalFieldDesc ff = (LocalFieldDesc) f.foreignFields.get(i);

            if (action == QueryPlan.ACT_INSERT) {
                // For inserts into the join table, we get the values we are inserting
                // for the parent object and the added object.
                ColumnElement fc = (ColumnElement) f.assocForeignColumns.get(i);

                addColumn(fc, ff.getValue(sm));
            } else if (action == QueryPlan.ACT_DELETE) {
                LocalFieldDesc aff = (LocalFieldDesc) f.assocForeignFields.get(i);

                // For deletes from the join table, we get the constraint values
                // from the parent object and the remove object.
                addConstraint(aff, ff.getValue(sm));
            }
        }
    }

    /**
     * Redefines processConstraintValue in order to skip the creation of
     * an InputValue in the case of batch.
     */
    protected void processConstraintValue(ConstraintValue node, StringBuffer result) {
        result.append("?"); // NOI18N
        if (!batch)
            generateInputValueForConstraintValueNode(node);
    }

    /**
     * Returns the cached db statement for the specified connection.
     * If there is not any statement for this connection in the cache,
     * then a new statement is created.
     * @param tran the transaction
     * @param conn the connection
     * @return the statement
     */
    public DBStatement getDBStatement(Transaction tran, Connection conn)
        throws SQLException
    {
        DBStatement dbStatement = null;

        synchronized (dbStatementCache)
        {
            // dbStatement cachelookup
            dbStatement = (DBStatement)dbStatementCache.get(tran);

            if (dbStatement == null) {
                dbStatement = new DBStatement(conn, getText(),
                                              tran.getUpdateTimeout());
                // put dbStatement in cache
                dbStatementCache.put(tran, dbStatement);
            }
        }

        return dbStatement;
    }

    /** */
    public boolean exceedsBatchThreshold(Transaction tran)
    {
        synchronized (dbStatementCache)
        {
            DBStatement dbStatement = (DBStatement)dbStatementCache.get(tran);
            return (dbStatement != null) && dbStatement.exceedsBatchThreshold();
        }
    }

    /**
     * Removes the db statement for the specified connection from the cache
     * and closes this statement.
     * @param tran the transaction
     */
    public DBStatement removeDBStatement(Transaction tran)
    {
        synchronized (dbStatementCache)
        {
            DBStatement s = (DBStatement)dbStatementCache.remove(tran);
            return s;
        }
    }

    public void bindInputColumns(DBStatement s,
                                 UpdateObjectDescImpl updateDesc)
            throws SQLException {

        // bind set clause (if necessary)
        for (Iterator i = getColumnRefs().iterator(); i.hasNext(); ) {
            bindInputColumn(s, (ColumnRef)i.next(), updateDesc, false );
        }
        // bind where clause (if necessary)
        for (Iterator i = columnRefsForWhereClause.iterator(); i.hasNext(); ) {
            bindInputColumn(s, (ColumnRef) i.next(), updateDesc,
                    updateDesc.isBeforeImageRequired());
        }

    }

    /**
     * Binds the value in the specified update descriptor corresponding
     * with the specified column reference to the specified statement.
     * @param stmt the statement
     * @param columnRef the column reference
     * @param updateDesc the update descriptor
     * @throws SQLException thrown by setter methods on java.sql.PreparedStatement
     */
    private void bindInputColumn(DBStatement stmt,
                                 ColumnRef columnRef,
                                 UpdateObjectDescImpl updateDesc,
                                 boolean getBeforeValue) throws SQLException {

        Object inputValue = getInputValue(updateDesc, columnRef, getBeforeValue);
        stmt.bindInputColumn(columnRef.getIndex(), inputValue,
                columnRef.getColumnElement(), vendorType);
    }

    /**
     * Get Input values to be bound to this statement.
     * @param updateDesc The update descriptor.
     * @return An Object array containing input values to be bound to this statement.
     */
    private Object[] getInputValues(UpdateObjectDescImpl updateDesc) {
        Object[] inputValues =
                new Object[getColumnRefs().size() + columnRefsForWhereClause.size()];
        for (Iterator i = getColumnRefs().iterator(); i.hasNext(); ) {
            ColumnRef columnRef = (ColumnRef)i.next();
            // columnRef's index are 1 based.
            inputValues[columnRef.getIndex() - 1] = getInputValue(updateDesc, columnRef, false);
        }
        final boolean getBeforeValue = updateDesc.isBeforeImageRequired();
        for (Iterator i = columnRefsForWhereClause.iterator(); i.hasNext(); ) {
            ColumnRef columnRef = (ColumnRef)i.next();
            inputValues[columnRef.getIndex() - 1] = getInputValue(updateDesc, columnRef, getBeforeValue);
        }
        return inputValues;
    }

    /**
     * Gets formatted sql text corrsponding to this statement object. The text
     * also contains values for input to the statement.
     * @param updateDesc the updateDesc.
     * @return formatted sql text corrsponding to this statement object.
     */
    public String getFormattedSQLText(UpdateObjectDescImpl updateDesc) {
        return formatSqlText(getText(), getInputValues(updateDesc));
    }

    /**
     * Gets input value corrsponding to given columnRef from given updateDesc
     * @param updateDesc updateDesc pointing to the input values
     * @param columnRef The columnRef. It always contains
     * the <code>LocalFieldDesc for the field.
     * @param getBeforeValue If true, value returned is fetched from beforeImage
     * if false, the value returned is fetched from afterImage.
     * @return input value corrsponding to given columnRef from given updateDesc.
     */
    private static Object getInputValue(UpdateObjectDescImpl updateDesc,
                                        ColumnRef columnRef,
                                        boolean getBeforeValue) {
        Object value;
        LocalFieldDesc field = (LocalFieldDesc) columnRef.getValue();

        if (field.isVersion()) {
            // Bind the value from the after image for version fields,
            // as they're incremented internally after each flush.
            // Version fields must not be modified from "outside".
            value = updateDesc.getAfterValue(field);
        }  else {
            value = getBeforeValue ? updateDesc.getBeforeValue(field) :
                    updateDesc.getAfterValue(field);
        }

        return value;
    }

    public void addVersionColumn(ColumnElement versionColumn) {
        if (versionColumns == null) {
            versionColumns = new ArrayList();
        }
        versionColumns.add(versionColumn);
    }
}

Other Glassfish examples (source code examples)

Here is a short list of links related to this Glassfish UpdateStatement.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.