2008-11-18 11 views
13

Para implementar el código de acceso a datos en nuestra aplicación, necesitamos un marco para envolver jdbc (ORM no es nuestra elección, debido a la escalabilidad).contenedor jdbc simple

El marco más genial con el que solía trabajar es Spring-Jdbc. Sin embargo, la política de mi compañía es evitar dependencias externas, especialmente primavera, J2EE, etc. Así que estamos pensando en escribir nuestro propio framework jdbc hecho a mano, con funcionalidades similares Spring-jdbc: mapeo de filas, manejo de errores, características de soporte de java5, pero sin soporte de transacción.

¿Alguien tiene experiencia en escribir este framework jdbc wrapper? Si alguien tiene experiencia en el uso de otros frameworks jdbc wrapper, por favor comparta su experiencia.

Gracias de antemano.

+10

"la política de mi empresa es evitar dependencias externas, especialmente la primavera, J2EE, etc." wow esto suena como una pesadilla. Suena como un ciclo sin fin de reinventar la rueda –

+7

¿J2EE es una "dependencia externa"? – yegor256

+0

Si está buscando una ejecución de SQL simplista para la asignación de objetos, mybatis es una opción. No lo llamaría un ORM en el sentido de que no hace gráficos de objetos como lo haría hibernate. Simplemente le permite ejecutar sql, y obtener parámetros desde su entrada, o asignar columnas a objetos de salida. – Matt

Respuesta

13

Escribimos nuestra propia envoltura. Este tema es digno de un papel, pero dudo que alguna vez tengo tiempo para escribir, así que aquí están algunos puntos clave:

  • Nos abrazamos sql y no hizo ningún intento de ocultarlo. el único cambio fue agregar soporte para los parámetros con nombre. los parámetros son importantes porque no fomentamos el uso de sql sobre la marcha (por razones de seguridad) y siempre usamos PreparedStatements.

  • para la gestión de la conexión, utilizamos Apache DBCP. Esto fue conveniente en ese momento, pero no está claro cuánto de esto se necesita con las implementaciones modernas de JDBC (faltan los documentos sobre este tema). DBCP también agrupa declaraciones preparadas.

  • no nos molestamos con la asignación de filas. en su lugar (para consultas) usamos algo similar al ResultSetHandler de Apache dbutil, que le permite "alimentar" el conjunto de resultados en un método que luego puede volcar la información donde quiera. Esto es más flexible y, de hecho, no sería difícil implementar un ResultSetHandler para la asignación de filas. para inserciones/actualizaciones creamos una clase de registro genérica (básicamente un hashmap con algunas campanas y silbatos adicionales). El mayor problema con el mapeo de filas (para nosotros) es que estás atascado tan pronto como haces una consulta "interesante" porque puedes tener campos que se asignan a diferentes clases; porque puede tener una estructura de clase jerárquica pero un conjunto de resultados plano; o porque el mapeo es complejo y depende de los datos.

  • construimos en el registro de errores. para el manejo de excepciones: en una consulta atrapamos y registramos, pero para una actualización atrapamos, registramos y volvemos a lanzar las excepciones no verificadas.

  • proporcionamos soporte de transacciones utilizando un enfoque de envoltura. la persona que llama proporciona el código que realiza la transacción, y nos aseguramos de que la transacción se administre correctamente, sin posibilidad de olvidar terminar la transacción y con la reversión y el manejo de error incorporado.

  • Más adelante, agregamos un esquema de relación muy simplista que permite aplicar una única actualización/inserción a un registro y todas sus dependencias. para mantener las cosas simples, no usamos esto en las consultas, y específicamente decidimos no admitir esto con las eliminaciones porque es más confiable usar las eliminaciones en cascada.

Este envoltorio se ha utilizado con éxito en dos proyectos hasta la fecha. Es, por supuesto, liviano, pero en estos días todo el mundo dice que su código es liviano. Más importante aún, aumenta la productividad del programador, disminuye el número de errores (y hace que los problemas sean más fáciles de rastrear), y es relativamente fácil de rastrear si es necesario porque no creemos en agregar muchas capas solo para proporcionar una arquitectura hermosa.

5

Spring-JDBC es fantástico. Considere que para un proyecto de código abierto como Spring se minimiza la desventaja de la dependencia externa. Puede adoptar la versión más estable de Spring que satisfaga sus requisitos de abstracción JDBC y sabe que siempre podrá modificar el código fuente si alguna vez se encuentra con un problema, sin depender de un tercero externo. También puede examinar la implementación de cualquier inquietud de seguridad que pueda tener su organización con un código escrito por un tercero.

1

Probar JdbcSession desde jcabi-jdbc. Es tan simple como debería ser JDBC, por ejemplo:

String name = new JdbcSession(source) 
    .sql("SELECT name FROM foo WHERE id = ?") 
    .set(123) 
    .select(new SingleOutcome<String>(String.class)); 

Eso es todo.

1

Esto suena como una decisión con poca visión corta. Considere el costo de desarrollar/mantener dicho marco, especialmente cuando puede obtenerlo, y su código fuente es gratuito. No solo no tiene que hacer el desarrollo usted mismo, puede modificarlo a voluntad si es necesario.

Dicho esto, lo que realmente necesita duplicar es la noción de JdbcTemplate y sus devoluciones (PreparedStatementCreator, PreparedStatementCallback), así como RowMapper/RowCallbackHandler. No debería ser demasiado complicado escribir algo como esto (especialmente teniendo en cuenta que no tiene que hacer gestión de transacciones).

Howver, como ya he dicho, ¿por qué escribirlo cuando lo puede obtener de forma gratuita y modificar el código fuente como mejor le parezca?

2

El que prefiero: Dalesbred. Está licenciado por MIT.

Un ejemplo simple de obtener todas las filas para una clase personalizada (Departamento).

List<Department> departments = db.findAll(Department.class, 
    "select id, name from department"); 

cuando la clase personalizada se define como:

public final class Department { 
    private final int id; 
    private final String name; 

    public Department(int id, String name) { 
     this.id = id; 
     this.name = name; 
    } 
} 

Negación: Es por una empresa para la que trabajo.