public static Sql newInstance(
            @NamedParam(value = "url", type = String.class, required = true)
            @NamedParam(value = "properties", type = Properties.class)
            @NamedParam(value = "driverClassName", type = String.class)
            @NamedParam(value = "driver", type = String.class)
            @NamedParam(value = "user", type = String.class)
            @NamedParam(value = "password", type = String.class)
            @NamedParam(value = "cacheNamedQueries", type = Boolean.class)
            @NamedParam(value = "cacheStatements", type = Boolean.class)
            @NamedParam(value = "enableNamedQueries", type = Boolean.class)
            @NamedParam(value = "resultSetConcurrency", type = Integer.class)
            @NamedParam(value = "resultSetHoldability", type = Integer.class)
            @NamedParam(value = "resultSetType", type = Integer.class)
            // TODO below will be deleted once we fix type checker to understand
            // readonly Map otherwise seen as Map<String, Serializable>
            @NamedParam(value = "unused", type = Object.class)
            Map<String, Object> args) throws SQLException, ClassNotFoundException {
        if (!args.containsKey("url"))
            throw new IllegalArgumentException("Argument 'url' is required");

        if (args.get("url") == null)
            throw new IllegalArgumentException("Argument 'url' must not be null");

        if (args.containsKey("driverClassName") && args.containsKey("driver"))
            throw new IllegalArgumentException("Only one of 'driverClassName' and 'driver' should be provided");

        // Make a copy so destructive operations will not affect the caller
        Map<String, Object> sqlArgs = new HashMap<String, Object>(args);

        sqlArgs.remove("unused"); // TODO remove
        Object driverClassName = sqlArgs.remove("driverClassName");
        if (driverClassName == null) driverClassName = sqlArgs.remove("driver");
        if (driverClassName != null) loadDriver(driverClassName.toString());

        Properties props = (Properties) sqlArgs.remove("properties");
        if (props != null && sqlArgs.containsKey("user"))
            throw new IllegalArgumentException("Only one of 'properties' and 'user' should be supplied");
        if (props != null && sqlArgs.containsKey("password"))
            throw new IllegalArgumentException("Only one of 'properties' and 'password' should be supplied");
        if (sqlArgs.containsKey("user") ^ sqlArgs.containsKey("password"))
            throw new IllegalArgumentException("Found one but not both of 'user' and 'password'");

        Object url = sqlArgs.remove("url");
        Connection connection;
        LOG.fine("url = " + url);
        if (props != null) {
            connection = DriverManager.getConnection(url.toString(), props);
            if (LOG.isLoggable(Level.FINE)) {
                if (!props.containsKey("password")) {
                    LOG.fine("props = " + props);
                } else {
                    // don't log the password
                    Properties propsCopy = new Properties();
                    propsCopy.putAll(props);
                    propsCopy.setProperty("password", "***");
                    LOG.fine("props = " + propsCopy);
                }
            }
        } else if (sqlArgs.containsKey("user")) {
            Object user = sqlArgs.remove("user");
            LOG.fine("user = " + user);
            Object password = sqlArgs.remove("password");
            LOG.fine("password = " + (password == null ? "null" : "***"));
            connection = DriverManager.getConnection(url.toString(),
                    (user == null ? null : user.toString()),
                    (password == null ? null : password.toString()));
        } else {
            LOG.fine("No user/password specified");
            connection = DriverManager.getConnection(url.toString());
        }

        Sql result = (Sql) InvokerHelper.invokeConstructorOf(Sql.class, sqlArgs);
        result.setConnection(connection);
        return result;
    }
public static Sql newInstance ( @ NamedParam ( value = "url" , type = String . class , required = true ) @ NamedParam ( value = "properties" , type = Properties . class ) @ NamedParam ( value = "driverClassName" , type = String . class ) @ NamedParam ( value = "driver" , type = String . class ) @ NamedParam ( value = "user" , type = String . class ) @ NamedParam ( value = "password" , type = String . class ) @ NamedParam ( value = "cacheNamedQueries" , type = Boolean . class ) @ NamedParam ( value = "cacheStatements" , type = Boolean . class ) @ NamedParam ( value = "enableNamedQueries" , type = Boolean . class ) @ NamedParam ( value = "resultSetConcurrency" , type = Integer . class ) @ NamedParam ( value = "resultSetHoldability" , type = Integer . class ) @ NamedParam ( value = "resultSetType" , type = Integer . class ) @ NamedParam ( value = "unused" , type = Object . class ) Map < String , Object > args ) throws SQLException , ClassNotFoundException { if ( ! args . containsKey ( "url" ) ) throw new IllegalArgumentException ( "Argument 'url' is required" ) ; if ( args . get ( "url" ) == null ) throw new IllegalArgumentException ( "Argument 'url' must not be null" ) ; if ( args . containsKey ( "driverClassName" ) && args . containsKey ( "driver" ) ) throw new IllegalArgumentException ( "Only one of 'driverClassName' and 'driver' should be provided" ) ; Map < String , Object > sqlArgs = new HashMap < String , Object > ( args ) ; sqlArgs . remove ( "unused" ) ; Object driverClassName = sqlArgs . remove ( "driverClassName" ) ; if ( driverClassName == null ) driverClassName = sqlArgs . remove ( "driver" ) ; if ( driverClassName != null ) loadDriver ( driverClassName . toString ( ) ) ; Properties props = ( Properties ) sqlArgs . remove ( "properties" ) ; if ( props != null && sqlArgs . containsKey ( "user" ) ) throw new IllegalArgumentException ( "Only one of 'properties' and 'user' should be supplied" ) ; if ( props != null && sqlArgs . containsKey ( "password" ) ) throw new IllegalArgumentException ( "Only one of 'properties' and 'password' should be supplied" ) ; if ( sqlArgs . containsKey ( "user" ) ^ sqlArgs . containsKey ( "password" ) ) throw new IllegalArgumentException ( "Found one but not both of 'user' and 'password'" ) ; Object url = sqlArgs . remove ( "url" ) ; Connection connection ; LOG . fine ( "url = " + url ) ; if ( props != null ) { connection = DriverManager . getConnection ( url . toString ( ) , props ) ; if ( LOG . isLoggable ( Level . FINE ) ) { if ( ! props . containsKey ( "password" ) ) { LOG . fine ( "props = " + props ) ; } else { Properties propsCopy = new Properties ( ) ; propsCopy . putAll ( props ) ; propsCopy . setProperty ( "password" , "***" ) ; LOG . fine ( "props = " + propsCopy ) ; } } } else if ( sqlArgs . containsKey ( "user" ) ) { Object user = sqlArgs . remove ( "user" ) ; LOG . fine ( "user = " + user ) ; Object password = sqlArgs . remove ( "password" ) ; LOG . fine ( "password = " + ( password == null ? "null" : "***" ) ) ; connection = DriverManager . getConnection ( url . toString ( ) , ( user == null ? null : user . toString ( ) ) , ( password == null ? null : password . toString ( ) ) ) ; } else { LOG . fine ( "No user/password specified" ) ; connection = DriverManager . getConnection ( url . toString ( ) ) ; } Sql result = ( Sql ) InvokerHelper . invokeConstructorOf ( Sql . class , sqlArgs ) ; result . setConnection ( connection ) ; return result ; }
Creates a new Sql instance given parameters in a Map.
Recognized keys for the Map include:
<pre>
driverClassName the fully qualified class name of the driver class
driver          a synonym for driverClassName
url             a database url of the form: <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>
user            the database user on whose behalf the connection is being made
password        the user's password
properties      a list of arbitrary string tag/value pairs as connection arguments;
normally at least a "user" and "password" property should be included
<em>other</em>           any of the public setter methods of this class may be used with property notation
e.g. <em>cacheStatements: true, resultSetConcurrency: ResultSet.CONCUR_READ_ONLY</em>
</pre>
Of these, '<code>url</code>' is required. Others may be needed depending on your database.<br>
If '<code>properties</code>' is supplied, neither '<code>user</code>' nor '<code>password</code>' should be supplied.<br>
If one of '<code>user</code>' or '<code>password</code>' is supplied, both should be supplied.
<p>
Example usage:
<pre>
import groovy.sql.Sql
import static java.sql.ResultSet.*

def sql = Sql.newInstance(
url:'jdbc:hsqldb:mem:testDB',
user:'sa',
password:'',
driver:'org.hsqldb.jdbc.JDBCDriver',
cacheStatements: true,
resultSetConcurrency: CONCUR_READ_ONLY
)
</pre>

@param args a Map contain further arguments
@return a new Sql instance with a connection
@throws SQLException           if a database access error occurs
@throws ClassNotFoundException if the driver class cannot be found or loaded