All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.avaje.ebeaninternal.server.persist.Binder Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2006  Robin Bygrave
 * 
 * This file is part of Ebean.
 * 
 * Ebean is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *  
 * Ebean is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Ebean; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA  
 */
package com.avaje.ebeaninternal.server.persist;

import java.math.BigDecimal;
import java.sql.CallableStatement;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.persistence.PersistenceException;

import com.avaje.ebeaninternal.api.BindParams;
import com.avaje.ebeaninternal.server.core.Message;
import com.avaje.ebeaninternal.server.type.DataBind;
import com.avaje.ebeaninternal.server.type.ScalarType;
import com.avaje.ebeaninternal.server.type.TypeManager;

/**
 * Binds bean values to a PreparedStatement.
 */
public class Binder {

	private static final Logger logger = Logger.getLogger(Binder.class.getName());

	//private final Calendar calendar;

	private final TypeManager typeManager;

	/**
	 * Set the PreparedStatement with which to bind variables to.
	 */
	public Binder(TypeManager typeManager) {

		this.typeManager = typeManager;
		//this.calendar = new GregorianCalendar();
	}

	/**
	 * Bind the values to the Prepared Statement.
	 */
	public void bind(BindValues bindValues, DataBind dataBind, StringBuilder bindBuf)
			throws SQLException {

		String logPrefix = "";

		ArrayList list = bindValues.values();
		for (int i = 0; i < list.size(); i++) {
			BindValues.Value bindValue = (BindValues.Value) list.get(i);
			if (bindValue.isComment()) {
				if (bindBuf != null) {
					bindBuf.append(bindValue.getName());
					if (logPrefix.equals("")) {
						logPrefix = ", ";
					}
				}
			} else {
				Object val = bindValue.getValue();
				int dt = bindValue.getDbType();
				bindObject(dataBind, val, dt);

				if (bindBuf != null) {
					bindBuf.append(logPrefix);
					if (logPrefix.equals("")) {
						logPrefix = ", ";
					}
					bindBuf.append(bindValue.getName());
					bindBuf.append("=");
					if (isLob(dt)) {
						bindBuf.append("[LOB]");
					} else {
						bindBuf.append(String.valueOf(val));
					}
				}
			}
		}
	}

	/**
	 * Bind the list of positionedParameters in BindParams.
	 */
	public String bind(BindParams bindParams, DataBind dataBind)
		throws SQLException {

		StringBuilder bindLog = new StringBuilder();
		bind(bindParams, dataBind, bindLog);
		return bindLog.toString();
	}

	/**
	 * Bind the list of positionedParameters in BindParams.
	 */
	public void bind(BindParams bindParams, DataBind dataBind, StringBuilder bindLog)
		throws SQLException {

		bind(bindParams.positionedParameters(), dataBind, bindLog);
	}
	
	/**
	 * Bind the list of parameters..
	 */
	public void bind(List list, DataBind dataBind, StringBuilder bindLog)
			throws SQLException {

		CallableStatement cstmt = null;

		if (dataBind.getPstmt() instanceof CallableStatement) {
			cstmt = (CallableStatement) dataBind.getPstmt();
		}

		// the iterator is assumed to be in the correct order
		Object value = null;
		try {
			for (int i = 0; i < list.size(); i++) {

				BindParams.Param param = list.get(i);

				if (param.isOutParam() && cstmt != null){
					cstmt.registerOutParameter(dataBind.nextPos(), param.getType());
					if (param.isInParam()) {
					    dataBind.decrementPos();
					}
				}
				if (param.isInParam()) {
					value = param.getInValue();
					if (bindLog != null) {
					    if (param.isEncryptionKey()){
		                    bindLog.append("****");
					    } else {
	                        bindLog.append(value);					        
					    }
						bindLog.append(", ");
					}
					if (value == null) {
						// this doesn't work for query predicates
						bindObject(dataBind, null, param.getType());
					} else {
						bindObject(dataBind, value);
					}
				}
			}

		} catch (SQLException ex) {
			logger.warning(Message.msg("fetch.bind.error", "" + (dataBind.currentPos() - 1), value));
			throw ex;
		}
	}

	/**
	 * Bind an Object with unknown data type.
	 */
	public void bindObject(DataBind dataBind, Object value) throws SQLException {

		if (value == null) {
			// null of unknown type
			bindObject(dataBind, null, Types.OTHER);

		} else {

			ScalarType type = typeManager.getScalarType(value.getClass());
			if (type == null){
				// the type is not registered with the TypeManager.
				String msg = "No ScalarType registered for "+value.getClass();
				throw new PersistenceException(msg);
				
			} else if (!type.isJdbcNative()) {
				// convert to a JDBC native type
				value = type.toJdbcType(value);
			}

			int dbType = type.getJdbcType();
			bindObject(dataBind, value, dbType);
		}
	}

	/**
	 * bind a single value.
	 * 

* Note that java.math.BigInteger is supported by converting it to a Long. *

*

* Note if we get a java.util.Date or java.util.Calendar then these have * been anonymously passed in (UpdateSql etc). There is a global setting to * convert then to a java.sql.Date or java.sql.Timestamp for binding. The * default is that both are converted to java.sql.Timestamp. *

*/ public void bindObject(DataBind dataBind, Object data, int dbType) throws SQLException { if (data == null){ dataBind.setNull(dbType); return; } switch (dbType) { case java.sql.Types.LONGVARCHAR: bindLongVarChar(dataBind, data); break; case java.sql.Types.LONGVARBINARY: bindLongVarBinary(dataBind, data); break; case java.sql.Types.CLOB: bindClob(dataBind, data); break; case java.sql.Types.BLOB: bindBlob(dataBind, data); break; default: bindSimpleData(dataBind, dbType, data); } } /** * Binds the value to the statement according to the data type. */ private void bindSimpleData(DataBind b, int dataType, Object data) throws SQLException { try { switch (dataType) { case java.sql.Types.BOOLEAN: Boolean bo = (Boolean) data; b.setBoolean(bo.booleanValue()); break; case java.sql.Types.BIT: // Types.BIT should map to Java Boolean Boolean bitBool = (Boolean) data; b.setBoolean(bitBool.booleanValue()); break; case java.sql.Types.VARCHAR: b.setString((String) data); break; case java.sql.Types.CHAR: b.setString(data.toString()); break; case java.sql.Types.TINYINT: b.setByte(((Byte) data).byteValue()); break; case java.sql.Types.SMALLINT: b.setShort(((Short) data).shortValue()); break; case java.sql.Types.INTEGER: b.setInt(((Integer) data).intValue()); break; case java.sql.Types.BIGINT: b.setLong(((Long) data).longValue()); break; case java.sql.Types.REAL: b.setFloat(((Float) data).floatValue()); break; case java.sql.Types.FLOAT: // DB Float in theory maps to Java Double type b.setDouble(((Double) data).doubleValue()); break; case java.sql.Types.DOUBLE: b.setDouble(((Double) data).doubleValue()); break; case java.sql.Types.NUMERIC: b.setBigDecimal((BigDecimal) data); break; case java.sql.Types.DECIMAL: b.setBigDecimal((BigDecimal) data); break; case java.sql.Types.TIME: //pstmt.setTime(index, (java.sql.Time) data, calendar); b.setTime((java.sql.Time) data); break; case java.sql.Types.DATE: //pstmt.setDate(index, (java.sql.Date) data, calendar); b.setDate((java.sql.Date) data); break; case java.sql.Types.TIMESTAMP: //pstmt.setTimestamp(index, (java.sql.Timestamp) data, calendar); b.setTimestamp((java.sql.Timestamp) data); break; case java.sql.Types.BINARY: b.setBytes((byte[]) data); break; case java.sql.Types.VARBINARY: b.setBytes((byte[]) data); break; case java.sql.Types.OTHER: b.setObject(data); break; case java.sql.Types.JAVA_OBJECT: // Not too sure about this. b.setObject(data); break; default: String msg = Message.msg("persist.bind.datatype", "" + dataType, "" + b.currentPos()); throw new SQLException(msg); } } catch (Exception e) { String dataClass = "Data is null?"; if (data != null) { dataClass = data.getClass().getName(); } String m = "Error with property[" + b.currentPos() + "] dt[" + dataType + "]"; m += "data[" + data + "][" + dataClass + "]"; throw new PersistenceException(m, e); } } /** * Bind String data to a LONGVARCHAR column. */ private void bindLongVarChar(DataBind b, Object data) throws SQLException { String sd = (String) data; b.setClob(sd); } /** * Bind byte[] data to a LONGVARBINARY column. */ private void bindLongVarBinary(DataBind b, Object data) throws SQLException { byte[] bytes = (byte[]) data; b.setBlob(bytes); } /** * Bind String data to a CLOB column. */ private void bindClob(DataBind b, Object data) throws SQLException { String sd = (String) data; b.setClob(sd); } /** * Bind byte[] data to a BLOB column. */ private void bindBlob(DataBind b, Object data) throws SQLException { byte[] bytes = (byte[]) data; b.setBlob(bytes); } private boolean isLob(int dbType) { switch (dbType) { case Types.CLOB: return true; case Types.LONGVARCHAR: return true; case Types.BLOB: return true; case Types.LONGVARBINARY: return true; default: return false; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy