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

com.ninja_squad.dbsetup.bind.Binders Maven / Gradle / Ivy

There is a newer version: 2.1.0
Show newest version
/*
 * The MIT License
 *
 * Copyright (c) 2012-2016, Ninja Squad
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.ninja_squad.dbsetup.bind;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.TimeZone;

/**
 * Utility class allowing to get various kinds of binders. The {@link DefaultBinderConfiguration} uses binders
 * returned by this class, based on the type of the parameter.
 * @author JB Nizet
 */
public final class Binders {

    private static final Binder DEFAULT_BINDER = new DefaultBinder();
    private static final Binder DATE_BINDER = new DateBinder();
    private static final Binder TIMESTAMP_BINDER = new TimestampBinder();
    private static final Binder DECIMAL_BINDER = new DecimalBinder();
    private static final Binder INTEGER_BINDER = new IntegerBinder();
    private static final Binder TIME_BINDER = new TimeBinder();
    private static final Binder STRING_BINDER = new StringBinder();

    private Binders() {
    }

    /**
     * Returns the default binder. This binder is normally used for columns of a type that is not handled by the other
     * binders. It is also used when the metadata are not used and the Insert thus doesn't know the type of the column.
     * It simply uses stmt.setObject() to bind the parameter, except if the value being bound is of some
     * some well-known type not handled by JDBC:
     * 
    *
  • enum: the name of the enum is bound
  • *
  • java.util.Date: the date is transformed to a java.sql.Timestamp
  • *
  • java.util.Calendar: the calendar is transformed to a java.sql.Timestamp, * and is passed as third argument of * PreparedStatement.setTimestamp() to pass the timezone
  • *
  • java.time.LocalDate: transformed to a java.sql.Date
  • *
  • java.time.LocalTime: transformed to a java.sql.Time
  • *
  • java.time.LocalDateTime: transformed to a java.sql.Timestamp
  • *
  • java.time.Instant: transformed to a java.sql.Timestamp
  • *
  • java.time.ZonedDateTime and OffsetDateTime: transformed to a * java.sql.Timestamp. The time zone is also used to create a Calendar passed as * third argument of PreparedStatement.setTimestamp() to pass the timezone
  • *
  • java.time.OffsetTime: transformed to a * java.sql.Time. The time zone is also used to create a Calendar passed as third * argument of PreparedStatement.setTime() to pass the timezone
  • *
*/ public static Binder defaultBinder() { return DEFAULT_BINDER; } /** * Returns a binder suitable for columns of type CHAR and VARCHAR. The returned binder supports values of type *
    *
  • String
  • *
  • enum: the name of the enum is used as bound value
  • *
  • Object: the toString() of the object is used as bound value
  • *
*/ public static Binder stringBinder() { return STRING_BINDER; } /** * Returns a binder suitable for columns of type DATE. The returned binder supports values of type *
    *
  • java.sql.Date
  • *
  • java.util.Date: the milliseconds of the date are used to construct a * java.sql.Date.
  • *
  • java.util.Calendar: the milliseconds of the calendar are used to construct a * java.sql.Date, and the calendar is passed as third argument of * PreparedStatement.setDate() to pass the timezone *
  • *
  • String: the string is transformed to a java.sql.Date using the Date.valueOf() * method
  • *
  • java.time.LocalDate: transformed to a java.sql.Date using * Date.valueOf()
  • *
  • java.time.LocalDateTime: transformed to a LocalDate (and thus ignoring the time), * and then transformed to a java.sql.Date using Date.valueOf()
  • *
  • java.time.Instantthe milliseconds of the instant are used to construct a * java.sql.Date.
  • *
  • java.time.ZonedDateTime and java.time.OffsetDateTime: transformed to an Instant * and then to a java.sql.Date. The time zone is also used to create a Calendar * passed as third argument of PreparedStatement.setDate() to pass the timezone
  • *
* If the value is none of these types, stmt.setObject() is used to bind the value. */ public static Binder dateBinder() { return DATE_BINDER; } /** * Returns a binder suitable for columns of type TIMESTAMP and TIMESTAMP_WITH_TIMEZONE. The returned binder * supports values of type *
    *
  • java.sql.Timestamp
  • *
  • java.util.Date: the milliseconds of the date are used to construct a * java.sql.Timestamp
  • *
  • java.util.Calendar: the milliseconds of the calendar are used to construct a * java.sql.Timestamp, and the calendar is passed as third argument of * PreparedStatement.setTimestamp() to pass the timezone
  • *
  • String: the string is transformed to a java.sql.Timestamp using the * Timestamp.valueOf() method, or using the java.sql.Date.valueOf() method if the * string has less than 19 characters
  • *
  • java.time.LocalDateTime: transformed to a java.sql.Timestamp using * Timestamp.valueOf()
  • *
  • java.time.LocalDate: transformed to a LocalDateTime with the time at start of day, * and then transformed to a java.sql.Timestamp using Timestamp.valueOf()
  • *
  • java.time.Instant: transformed to a java.sql.Timestamp using * Timestamp.from()
  • *
  • java.time.ZonedDateTime and java.time.OffsetDateTime: transformed to an Instant * and then to a java.sql.Timestamp using Timestamp.from(). The time zone is also * used to create a Calendar passed as third argument of * PreparedStatement.setTimestamp() to pass the timezone
  • *
* If the value is none of these types, stmt.setObject() is used to bind the value. */ public static Binder timestampBinder() { return TIMESTAMP_BINDER; } /** * Returns a binder suitable for columns of type TIME or TIME_WITH_TIMEZONE. The returned binder supports values * of type *
    *
  • java.sql.Time
  • *
  • java.util.Date: the milliseconds of the date are used to construct a * java.sql.Time
  • *
  • java.util.Calendar: the milliseconds of the calendar are used to construct a * java.sql.Time, and the calendar is passed as third argument of * PreparedStatement.setTimestamp() to pass the timezone *
  • *
  • String: the string is transformed to a java.sql.Time using the * Time.valueOf() method
  • *
  • java.time.LocalTime: transformed to a java.sql.Time using * Time.valueOf()
  • *
  • java.time.OffsetTime: transformed to a LocalTime and then to a * java.sql.Time using Time.valueOf(). The time zone is also * used to create a Calendar passed as third argument of * PreparedStatement.setTime() to pass the timezone
  • *
* If the value is none of these types, stmt.setObject() is used to bind the value. */ public static Binder timeBinder() { return TIME_BINDER; } /** * Returns a binder suitable for numeric, decimal columns. The returned binder supports values of type *
    *
  • String: the string is transformed to a java.math.BigDecimal using its constructor
  • *
* If the value is none of these types, stmt.setObject() is used to bind the value. */ public static Binder decimalBinder() { return DECIMAL_BINDER; } /** * Returns a binder suitable for numeric, integer columns. The returned binder supports values of type *
    *
  • BigInteger: the object is transformed to a String and bound using * stmt.setObject(), with BIGINT as target type. *
  • *
  • enum: the enum is transformed into an integer by taking its ordinal
  • *
  • String: the string is bound using stmt.setObject(), with BIGINT as * target type. *
  • *
* If the value is none of these types, stmt.setObject() is used to bind the value. */ public static Binder integerBinder() { return INTEGER_BINDER; } /** * The implementation for {@link Binders#stringBinder()} * @author JB Nizet */ private static final class StringBinder implements Binder { @Override public void bind(java.sql.PreparedStatement stmt, int param, Object value) throws java.sql.SQLException { if (value instanceof String) { stmt.setString(param, (String) value); } else if (value instanceof Enum) { stmt.setString(param, ((Enum) value).name()); } else if (value == null) { stmt.setObject(param, null); } else { stmt.setString(param, value.toString()); } } @Override public String toString() { return "Binders.stringBinder"; } } /** * The implementation for {@link Binders#timeBinder()} * @author JB Nizet */ private static final class TimeBinder implements Binder { @Override public void bind(java.sql.PreparedStatement stmt, int param, Object value) throws java.sql.SQLException { if (value instanceof Time) { stmt.setTime(param, (Time) value); } else if (value instanceof java.util.Date) { stmt.setTime(param, new Time(((java.util.Date) value).getTime())); } else if (value instanceof Calendar) { Calendar calendar = (Calendar) value; stmt.setTime(param, new Time(calendar.getTimeInMillis()), calendar); } else if (value instanceof String) { stmt.setTime(param, Time.valueOf((String) value)); } else if (value instanceof LocalTime) { stmt.setTime(param, Time.valueOf((LocalTime) value)); } else if (value instanceof OffsetTime) { OffsetTime offsetTime = (OffsetTime) value; stmt.setTime(param, Time.valueOf(offsetTime.toLocalTime()), Calendar.getInstance(TimeZone.getTimeZone(offsetTime.getOffset()))); } else { stmt.setObject(param, value); } } @Override public String toString() { return "Binders.timeBinder"; } } /** * The implementation for {@link Binders#integerBinder()} * @author JB Nizet */ private static final class IntegerBinder implements Binder { @Override public void bind(java.sql.PreparedStatement stmt, int param, Object value) throws java.sql.SQLException { if (value instanceof BigInteger) { stmt.setObject(param, value.toString(), Types.BIGINT); } else if (value instanceof Enum) { stmt.setInt(param, ((Enum) value).ordinal()); } else if (value instanceof String) { stmt.setObject(param, value, Types.BIGINT); } else { stmt.setObject(param, value); } } @Override public String toString() { return "Binders.integerBinder"; } } /** * The implementation for {@link Binders#decimalBinder()} * @author JB Nizet */ private static final class DecimalBinder implements Binder { @Override public void bind(java.sql.PreparedStatement stmt, int param, Object value) throws java.sql.SQLException { if (value instanceof String) { stmt.setBigDecimal(param, new BigDecimal((String) value)); } else { stmt.setObject(param, value); } } @Override public String toString() { return "Binders.decimalBinder"; } } /** * The implementation for {@link Binders#timestampBinder()} * @author JB Nizet */ private static final class TimestampBinder implements Binder { // the number of chars in yyyy-mm-dd hh:mm:ss private static final int MIN_NUMBER_OF_CHARS_FOR_TIMESTAMP = 19; @Override public void bind(java.sql.PreparedStatement stmt, int param, Object value) throws java.sql.SQLException { if (value instanceof Timestamp) { stmt.setTimestamp(param, (Timestamp) value); } else if (value instanceof java.util.Date) { stmt.setTimestamp(param, new Timestamp(((java.util.Date) value).getTime())); } else if (value instanceof Calendar) { stmt.setTimestamp(param, new Timestamp(((Calendar) value).getTimeInMillis()), (Calendar) value); } else if (value instanceof String) { String valueAsString = (String) value; if (valueAsString.length() >= MIN_NUMBER_OF_CHARS_FOR_TIMESTAMP) { stmt.setTimestamp(param, Timestamp.valueOf(valueAsString)); } else { Date valueAsDate = Date.valueOf(valueAsString); stmt.setTimestamp(param, new Timestamp(valueAsDate.getTime())); } } else if (value instanceof LocalDateTime) { LocalDateTime localDateTime = (LocalDateTime) value; stmt.setTimestamp(param, Timestamp.valueOf(localDateTime)); } else if (value instanceof Instant) { Instant instant = (Instant) value; stmt.setTimestamp(param, Timestamp.from(instant)); } else if (value instanceof ZonedDateTime) { ZonedDateTime zonedDateTime = (ZonedDateTime) value; stmt.setTimestamp(param, Timestamp.from(zonedDateTime.toInstant()), Calendar.getInstance(TimeZone.getTimeZone(zonedDateTime.getZone()))); } else if (value instanceof OffsetDateTime) { OffsetDateTime offsetDateTime = (OffsetDateTime) value; stmt.setTimestamp(param, Timestamp.from(offsetDateTime.toInstant()), Calendar.getInstance(TimeZone.getTimeZone(offsetDateTime.getOffset()))); } else if (value instanceof LocalDate) { LocalDate localDate = (LocalDate) value; stmt.setTimestamp(param, Timestamp.valueOf(localDate.atStartOfDay())); } else { stmt.setObject(param, value); } } @Override public String toString() { return "Binders.timestampBinder"; } } /** * The implementation for {@link Binders#dateBinder()} * @author JB Nizet */ private static final class DateBinder implements Binder { @Override public void bind(java.sql.PreparedStatement stmt, int param, Object value) throws java.sql.SQLException { if (value instanceof Date) { stmt.setDate(param, (Date) value); } else if (value instanceof java.util.Date) { stmt.setDate(param, new Date(((java.util.Date) value).getTime())); } else if (value instanceof Calendar) { Calendar calendar = (Calendar) value; stmt.setDate(param, new Date(calendar.getTimeInMillis()), calendar); } else if (value instanceof String) { stmt.setDate(param, Date.valueOf((String) value)); } else if (value instanceof LocalDate) { LocalDate localDate = (LocalDate) value; stmt.setDate(param, Date.valueOf(localDate)); } else if (value instanceof LocalDateTime) { LocalDateTime localDateTime = (LocalDateTime) value; stmt.setDate(param, Date.valueOf(localDateTime.toLocalDate())); } else if (value instanceof Instant) { Instant instant = (Instant) value; stmt.setDate(param, new Date(instant.toEpochMilli())); } else if (value instanceof ZonedDateTime) { ZonedDateTime zonedDateTime = (ZonedDateTime) value; stmt.setDate(param, new Date(zonedDateTime.toInstant().toEpochMilli()), Calendar.getInstance(TimeZone.getTimeZone(zonedDateTime.getZone()))); } else if (value instanceof OffsetDateTime) { OffsetDateTime offsetDateTime = (OffsetDateTime) value; stmt.setDate(param, new Date(offsetDateTime.toInstant().toEpochMilli()), Calendar.getInstance(TimeZone.getTimeZone(offsetDateTime.getOffset()))); } else { stmt.setObject(param, value); } } @Override public String toString() { return "Binders.dateBinder"; } } /** * The implementation for {@link Binders#defaultBinder()} * @author JB Nizet */ private static final class DefaultBinder implements Binder { @Override public void bind(java.sql.PreparedStatement stmt, int param, Object value) throws java.sql.SQLException { if (value instanceof Enum) { stmt.setString(param, ((Enum) value).name()); } else if (value instanceof java.util.Date) { stmt.setTimestamp(param, new Timestamp(((java.util.Date) value).getTime())); } else if (value instanceof Calendar) { Calendar calendar = (Calendar) value; stmt.setTimestamp(param, new Timestamp(calendar.getTime().getTime()), calendar); } else if (value instanceof LocalDate) { stmt.setDate(param, Date.valueOf((LocalDate) value)); } else if (value instanceof LocalTime) { stmt.setTime(param, Time.valueOf((LocalTime) value)); } else if (value instanceof LocalDateTime) { stmt.setTimestamp(param, Timestamp.valueOf((LocalDateTime) value)); } else if (value instanceof Instant) { stmt.setTimestamp(param, Timestamp.from((Instant) value)); } else if (value instanceof ZonedDateTime) { ZonedDateTime zonedDateTime = (ZonedDateTime) value; stmt.setTimestamp(param, Timestamp.from(zonedDateTime.toInstant()), Calendar.getInstance(TimeZone.getTimeZone(zonedDateTime.getZone()))); } else if (value instanceof OffsetDateTime) { OffsetDateTime offsetDateTime = (OffsetDateTime) value; stmt.setTimestamp(param, Timestamp.from(offsetDateTime.toInstant()), Calendar.getInstance(TimeZone.getTimeZone(offsetDateTime.getOffset()))); } else if (value instanceof OffsetTime) { OffsetTime offsetTime = (OffsetTime) value; stmt.setTime(param, Time.valueOf(offsetTime.toLocalTime()), Calendar.getInstance(TimeZone.getTimeZone(offsetTime.getOffset()))); } else { stmt.setObject(param, value); } } @Override public String toString() { return "Binders.defaultBinder"; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy