La mayoría de aplicaciones requieren acceso a una base de datos. En java existe JDBC que nos permite realizar esta tarea.
En una aplicación distribuida y escalable nos vemos en la necesidad de utilizar un pool de conexiones para no causar un problema de rendimiento. Por ejemplo, he creado servicios web (REST) que deseo sean consumidos desde dispositivos móviles, para ello necesito que los servicios sean escalables.

Ya que utilicé Spring Roo para crear la plantilla inicial del proyecto, este me agregó la siguiente configuración inicial.

applicationContext.xml

...
    <bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
        <property name="driverClassName" value="${database.driverClassName}"/>
        <property name="url" value="${database.url}"/>
        <!--<property name="username" value="${database.username}"/>-->
        <!--<property name="password" value="${database.password}"/>-->
        <property name="testOnBorrow" value="true"/>
        <property name="testOnReturn" value="true"/>
        <property name="testWhileIdle" value="true"/>
        <property name="timeBetweenEvictionRunsMillis" value="1800000"/>
        <property name="numTestsPerEvictionRun" value="3"/>
        <property name="minEvictableIdleTimeMillis" value="1800000"/>
        <property name="validationQuery" value="SELECT 1 FROM DUAL"/>
    </bean>
...

como podemos ver, esta configuración crea un DataSource de tipo org.apache.commons.dbcp.BasicDataSource. Este tipo de DataSource crea un pool de conexiones automáticamente. Genial!

Ahora, ¿cómo lo utilizamos en nuestras clases para poder ejecutar una consulta SQL?

Podríamos utilizarlo de la forma tradicional con JDBC

...
    @Autowired
    public DistritosServiceImpl(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public List<Distrito> getDistritos() {
        List<Distrito> distritos = new ArrayList<Distrito>();
        String sql = 
                "select id, nombre " +
                        "from distritos";
        Connection con = null;
        try{
            con = this.dataSource.getConnection();
            PreparedStatement stmt = con.prepareStatement(sql);
            ResultSet rs = stmt.executeQuery();
            while(rs.next()){
                distritos.add(new Distrito(rs.getInt("id"), rs.getString("nombre")));
            }
        }catch (Exception e){
            e.printStackTrace();
            if(con != null){
                try {
                    con.close();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return distritos;
    }
...

pero existe una mejor manera, utilizando JdbcTemplate

...
    @Autowired
    public DistritosServiceImpl(DataSource dataSource) {
        this.dataSource = dataSource;
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Override
    public List<Distrito> getDistritos() {
        String sql =
                "select id, nombre " +
                        "from distritos";
        return jdbcTemplate.query(sql, new RowMapper<Distrito>() {
            @Override
            public Distrito mapRow(ResultSet rs, int i) throws SQLException {
                return new Distrito(rs.getInt("id"), rs.getString("nombre"));
            }
        });
    }
...

Fuentes:

Anuncios

Al crear un DataSet con una consulta con parámetros, BIRT me arrojaba el error

org.eclipse.birt.data.engine.core.DataException: Failed to prepare the query execution for the data set: t_host
Cannot get the type for parameter: 1.
org.eclipse.birt.report.data.oda.jdbc.JDBCException: Cannot get parameter type.
SQL error #1:Unsupported feature

Al parecer el problema sólo se presenta con la base de datos de Oracle y ha sido resuelto a partir de la versión 4.2.1 de BIRT. Así que, si tienes una versión anterior, basta con actualizar para resolver el problema (Help->Check for Updates).

Fuentes:
eclipse forums

En una aplicación utilizo un TreeGrid para crear un menú de opciones. Los elementos del menú son obtenidos desde un servicio REST.

El TreeGrid lo creo de la siguiente forma

grdApplicaciones=new TreeGrid();
grdApplicaciones.setDataSource(new RestDataSource(){
{
setDataURL("api/rest/modulos");
setDataFormat(DSDataFormat.JSON);</p><pre>
<code>    DataSourceField fldId=new DataSourceField("id", FieldType.TEXT);
    fldId.setPrimaryKey(true);
    DataSourceField fldIdPadre=new DataSourceField("idPadre", FieldType.TEXT);
    fldIdPadre.setForeignKey(this.getID()+".id");
    DataSourceField fldNombre=new DataSourceField("nombre", FieldType.TEXT);
    setFields(fldId,fldIdPadre,fldNombre);
    setTitleField("nombre");
}
</code>
</pre><p>});
grdApplicaciones.addDataArrivedHandler(new DataArrivedHandler() {</p><pre>
<code>@Override
public void onDataArrived(DataArrivedEvent event) {
    grdApplicaciones.getData().setNameProperty("nombre");
}
</code>
</pre><p>});
grdApplicaciones.setAutoFetchData(true);
grdApplicaciones.setLoadDataOnDemand(false);

Los datos del servicio están en formato JSON y tienen una estructura id, idPadre y nombre. El manejador del evento “DataArrivedHandler” se encarga de establecer la propiedad “nombre” para que el TreeGrid la utilicé como el título de los nodos, además de utilizarla para formar la cadena que regresa el método getPath().

Fuentes:
http://forums.smartclient.com/showthread.php?t=4413

Si utilizas un DataSource para enlazar los datos a un control de SmartGwt y tienes la necesidad de filtrar por un rango de fechas, lo puedes hacer de la siguiente manera:

AdvancedCriteria criteria=new AdvancedCriteria(OperatorId.AND, new Criterion[]{
new Criterion(“inicio”, OperatorId.GREATEROREQUAL, inicio),
new Criterion(“inicio”, OperatorId.LESS_THAN, fin)
});
calendario.fetchData(criteria);

Notesé que a pesar de que la clase Criterion hereda de Criteria, no podemos utilizarla directamente en el método fetchData, por ejemplo:

Criterion criteria=new Criterion();
criteria.addCriteria(“inicio”, OperatorId.GREATEROREQUAL, inicio);
criteria.addCriteria(“inicio”, OperatorId.LESS_THAN, fin);
calendario.fetchData(criteria);

arrojaría el siguiente error:

Caused by: java.lang.NullPointerException: null

    at com.smartgwt.client.data.Criterion.addCriteria(Criterion.java:218)

    at com.smartgwt.client.data.Criterion.addCriteria(Criterion.java:276)

Los objetos Criterion siempre deberán usarse como parte de un AdvancedCriteria dado que su definición es:

A criterion is part of the definition of an com.smartgwt.client.data.AdvancedCriteria object, which is used to filter records according to search criteria.

I had a report which connects to an Oracle Database through JDBC to get data. Since I reinstalled eclipse and BIRT, my JDBC configuration was lost. Therefore when I tried to preview my report the following error was thrown:

Table TBL_EXPEDIENTES_ASIGNADOS:
An exception occurred during processing. Please see the following message for details:
Cannot open the connection for the driver: org.eclipse.birt.report.data.oda.jdbc.
    org.eclipse.birt.report.data.oda.jdbc.JDBCException: Cannot load JDBC Driver class: oracle.jdbc.OracleDriver

The only way I’ve found to manage your JDBC drivers is to open the new datasource dialog and select “JDBC Datasource”, put whatever name you like and press next. You should see a button with the label “Manage Drivers…”. Then you could add the ojdbc6.jar or whatever JDBC driver you need.