Hibernate vs JPA vs JDO – pros y contras de cada uno?

Estoy familiarizado con ORM como concepto, e incluso he usado nHibernate hace varios años para un proyecto .NET; sin embargo, no he seguido el tema de ORM en Java y no he tenido la oportunidad de utilizar ninguna de estas herramientas.

Pero, ahora puedo tener la oportunidad de comenzar a utilizar algunas herramientas ORM para una de nuestras aplicaciones, en un bash de alejarme de una serie de servicios web heredados.

Me está costando diferenciar la diferencia entre las especificaciones de JPA, lo que obtienes con la biblioteca de Hibernate y lo que JDO tiene para ofrecer.

Entonces, entiendo que esta pregunta es un poco abierta, pero esperaba obtener algunas opiniones sobre:

  • ¿Cuáles son los pros y los contras de cada uno?
  • ¿Qué recomendarías para un nuevo proyecto?
  • ¿Hay ciertas condiciones en las que tendría sentido usar un marco frente al otro?

Algunas notas:

  • JDO y JPA son especificaciones, no implementaciones.
  • La idea es que puede intercambiar implementaciones de JPA, si restringe su código para usar solo JPA estándar. (Lo mismo para JDO)
  • Hibernate se puede usar como una de esas implementaciones de JPA.
  • Sin embargo, Hibernate proporciona una API nativa, con funciones que van más allá de las de JPA.

OMI, recomendaría Hibernate.


Ha habido algunos comentarios / preguntas sobre lo que debe hacer si necesita usar funciones específicas de Hibernate. Hay muchas formas de ver esto, pero mi consejo sería:

  • Si no está preocupado por la perspectiva de la vinculación del proveedor, haga su elección entre Hibernate y otras implementaciones de JPA y JDO, incluidas las diversas extensiones específicas del proveedor en la toma de decisiones.

  • Si le preocupa la posibilidad de que un proveedor se ate y no puede usar JPA sin recurrir a extensiones específicas del proveedor, entonces no use JPA. (Lo mismo para JDO).

En realidad, es probable que deba sacrificar la preocupación por el vínculo del proveedor con la cantidad que necesita de esas extensiones específicas del proveedor.

Y también hay otros factores, como qué tan bien conocen usted / su personal las tecnologías respectivas, cuánto costarán los productos en licencias, y de quién es la historia que cree sobre lo que va a suceder en el futuro para JDO y JPA.

Asegúrese de evaluar la implementación de DataNucleus de JDO. Comenzamos con Hibernate porque parecía ser tan popular, pero pronto nos dimos cuenta de que no se trataba de una solución de persistencia 100% transparente. Hay demasiadas advertencias y la documentación está llena de “si tiene esta situación, entonces debe escribir su código de esta manera” que le quitó la diversión de modelar y codificar libremente como queramos. JDO nunca me ha obligado a ajustar mi código o mi modelo para que ‘funcione correctamente’. Solo puedo diseñar y codificar POJO simples como si fuera a usarlos ‘solo en memoria’, pero puedo persistir de forma transparente.

La otra ventaja de JDO / DataNucleus sobre hibernación es que no tiene toda la sobrecarga de reflexión de tiempo de ejecución y es más eficiente en cuanto a memoria porque usa mejora de código de bytes de tiempo de comstackción (quizás agregue 1 segundo a su tiempo de comstackción para un proyecto grande) que el patrón de proxy alimentado por la reflexión del tiempo de ejecución de hibernate.

Otra cosa que puede resultar molesto con Hibernate es que se trata de una referencia de lo que crees que es el objeto … a menudo es un “proxy” para el objeto. Sin el beneficio de la mejora del código de bytes, se requiere el patrón proxy para permitir la carga bajo demanda (es decir, evitar tirar todo el gráfico de objetos cuando se tira de un objeto de nivel superior). Esté preparado para anular equals y hashcode porque el objeto que cree que está haciendo referencia a menudo es simplemente un proxy para ese objeto.

Aquí hay un ejemplo de las frustraciones que obtendrá con Hibernate que no obtendrá con JDO:

http://blog.andrewbeacock.com/2008/08/how-to-implement-hibernate-safe-equals.html
http://burtbeckwith.com/blog/?p=53

Si le gusta la encoding de ‘soluciones’, entonces, seguro, Hibernate es para usted. Si aprecia el desarrollo limpio, puro, orientado a objetos y basado en modelos, donde pasa todo su tiempo modelando, diseñando y codificando, y nada de eso en soluciones desagradables, pase unas horas evaluando JDO / DataNucleus . Las horas invertidas se pagarán mil veces.

Actualización feb 2017

Desde hace bastante tiempo, DataNucleus implementa el estándar de persistencia JPA además del estándar de persistencia JDO, por lo que trasladar proyectos JPA existentes desde Hibernate a DataNucleus debería ser muy sencillo y puede obtener todos los beneficios de DataNucleus mencionados anteriormente con muy pocos cambios de código , Si alguna. Entonces, en términos de la pregunta, la elección de un estándar particular, JPA (solo RDBMS) vs JDO (RDBMS + No SQL + ODBMSes + otros), DataNucleus admite ambos, Hibernate está restringido solo a JPA.

Rendimiento de las actualizaciones de Hibernate DB

Otro aspecto a considerar cuando se elige un ORM es la eficiencia de su mecanismo de control sucio, que se vuelve muy importante cuando se necesita construir el SQL para actualizar los objetos que han cambiado en la transacción actual, especialmente cuando hay muchos objetos. Hay una descripción técnica detallada del mecanismo de control sucio de Hibernate en esta respuesta SO: JPA con inserto HIBERNATE muy lento

Recientemente evalué y elegí un marco de persistencia para un proyecto de Java y mis hallazgos son los siguientes:

Lo que estoy viendo es que el apoyo a favor de JDO es principalmente:

  • puede usar fonts de datos que no sean sql, db4o, hbase, ldap, bigtable, couchdb (complementos para cassandra), etc.
  • puede cambiar fácilmente de un origen de datos de sql a no de sql y viceversa.
  • no hay objetos proxy y, por lo tanto, menos dolor con respecto a las implementaciones hashcode () y equals ()
  • más POJO y, por lo tanto, se requieren menos soluciones
  • admite más tipos de relación y campo

y el apoyo a favor de JPA es principalmente:

  • más popular
  • jdo está muerto
  • no usa la mejora de bytecode

Veo muchas publicaciones pro-JPA de desarrolladores de JPA que claramente no han usado JDO / Datanucleus ofreciendo argumentos débiles para no usar JDO.

También veo muchas publicaciones de usuarios de JDO que migraron a JDO y, como resultado, están mucho más contentos.

Con respecto a que JPA sea más popular, parece que esto se debe en parte al soporte del proveedor de RDBMS en lugar de ser técnicamente superior. (Suena como VHS / Betamax para mí).

JDO y su implementación de referencia Datanucleus claramente no está muerto, como lo demuestra la adopción por parte de Google de GAE y el desarrollo activo en el código fuente (http://sourceforge.net/projects/datanucleus/).

He visto una serie de quejas sobre JDO debido a la mejora del código de bytes, pero todavía no hay una explicación de por qué es malo.

De hecho, en un mundo cada vez más obsesionado por las soluciones NoSQL, JDO (y la implementación de datanucleus) parece una apuesta mucho más segura.

Acabo de comenzar a usar JDO / Datanucleus y lo tengo configurado para que pueda cambiar fácilmente entre usar db4o y mysql. Es útil para el desarrollo rápido usar db4o y no tener que preocuparse demasiado por el esquema de DB y luego, una vez que el esquema se estabiliza para desplegarse en una base de datos. También estoy seguro de que más adelante podría desplegar toda o parte de mi aplicación en GAE o aprovechar el almacenamiento distribuido / map-reduce a la hbase / hadoop / cassandra sin demasiada refactorización.

Descubrí que el obstáculo inicial para empezar con Datanucleus es un poco complicado: la documentación en el sitio web de datanucleus es un poco difícil de conseguir; los tutoriales no son tan fáciles de seguir como me hubiera gustado. Habiendo dicho eso, la documentación más detallada sobre la API y el mapeo es muy buena una vez que superas la curva de aprendizaje inicial.

La respuesta es, depende de lo que quieras. Preferiría tener un código más limpio, no-vendor-lock-in, más pojo-orientado, opciones de nosql versos más populares.

Si quieres la sensación de calor y nerviosismo de que estás haciendo lo mismo que la mayoría de otros desarrolladores / ovejas, elige JPA / hibernate. Si quiere liderar en su campo, pruebe el JDO / Datanucleus y haga su propia elección.

¿Qué recomendarías para un nuevo proyecto?

Yo sugeriría ninguno! En su lugar, utilice la JdbcTemplate Spring DAO junto con RowMapper , RowMapper y RowCallbackHandler .

Mi propia experiencia personal con Hibernate es que el tiempo ahorrado desde el principio queda más que compensado por los días interminables que pasará en la línea tratando de comprender y depurar problemas como el comportamiento inesperado de la actualización en cascada.

Si está utilizando una base de datos relacional, cuanto más cerca esté de su código, más control tendrá. La capa DAO de Spring permite un control fino de la capa de mapeo, al tiempo que elimina la necesidad de un código repetitivo. Además, se integra en la capa de transacciones de Spring, lo que significa que puede agregar muy fácilmente (a través de AOP) un comportamiento transaccional complicado sin que esto se entrometa en su código (por supuesto, también lo obtiene con Hibernate).

JDO está muerto

JDO no está muerto, así que por favor revisa tus datos. JDO 2.2 fue lanzado en octubre de 2008 JDO 2.3 está en desarrollo.

Esto se desarrolla abiertamente, bajo Apache. Ha habido más lanzamientos que JPA, y su especificación ORM todavía está por delante incluso de las características propuestas de JPA2

JDO tiene funciones avanzadas que JPA, vea http://db.apache.org/jdo/jdo_v_jpa.html

Estoy usando JPA (implementación OpenJPA de Apache, que se basa en la base de código JDO de KODO que tiene más de 5 años y es extremadamente rápida / confiable). En mi humilde opinión, cualquier persona que le pida que omita las especificaciones le está dando malos consejos. Puse el tiempo y definitivamente fue recompensado. Con JDO o JPA puede cambiar los proveedores con cambios mínimos (JPA tiene una asignación de orm, por lo que estamos hablando de menos de un día para posiblemente cambiar de proveedor). Si tienes más de 100 mesas como yo, esto es enorme. Además, tienes built-in en caché con desalojos de caché en clúster y todo está bien. SQL / Jdbc está bien para consultas de alto rendimiento, pero la persistencia transparente es muy superior para escribir sus algoritmos y rutinas de entrada de datos. Solo tengo unas 16 consultas SQL en todo mi sistema (50k + líneas de código).

Cualquiera que diga que JDO está muerto es un traficante de FUD astroturfing y ellos lo saben.

JDO está vivo y bien. La especificación es aún más poderosa, madura y avanzada que la JPA mucho más joven y limitada.

Si desea limitarse solo a lo que está disponible en el estándar JPA, puede escribir en JPA y utilizar DataNucleus como una implementación de persistencia más transparente y de alto rendimiento que las otras implementaciones de JPA. Por supuesto, DataNucleus también implementa el estándar JDO si desea la flexibilidad y eficiencia del modelado que aporta JDO.

He estado investigando esto por mí mismo y no puedo encontrar una gran diferencia entre los dos. Creo que la gran elección es en qué implementación usas. Por mi parte, he estado considerando la plataforma DataNucleus ya que es una implementación agnóstica de almacenamiento de datos de ambas.

He utilizado Hibernate (implementación de JPA) y JPOX (implementación de JDO) en el mismo proyecto. JPOX funcionó bien, pero se topó con errores bastante rápido, donde algunas características del lenguaje Java 5 no eran compatibles en ese momento. Tenía problemas para jugar bien con las transacciones XA. Estaba generando el esquema de la base de datos desde los objetos JDO. Quería conectarse a una base de datos cada vez, lo que es molesto si su conexión Oracle no funciona.

Luego cambiamos a Hibernate. Estuvimos jugando solo con JPA puro por un tiempo, pero necesitábamos usar algunas de las características específicas de Hibernate para hacer el mapeo. Ejecutar el mismo código en múltiples bases de datos es muy fácil. Hibernate parece almacenar en caché los objetos agresivamente o simplemente tiene un extraño comportamiento de almacenamiento en caché a veces. Hay algunas construcciones DDL que Hibernate no puede manejar, por lo que se definen en un archivo adicional que se ejecuta para inicializar la base de datos. Cuando me he encontrado con un problema de Hibernate, a menudo hay muchas personas que se han encontrado con el mismo problema, lo que facilita la búsqueda de soluciones en Google. Finalmente, Hibernate parece estar bien diseñado y confiable.

Algunos otros respondedores han sugerido simplemente usar SQL. El caso de uso real asesino para el mapeo relacional de objetos es la prueba y el desarrollo. Las bases de datos que se crean para manejar grandes volúmenes de datos suelen ser costosas o difíciles de instalar. Son difíciles de probar con. Hay muchas bases de datos Java en la memoria que se pueden usar para probar, pero generalmente son inútiles para la producción. Poder usar una base de datos real, pero limitada, boostá la productividad de desarrollo y la confiabilidad del código.

Hice un WebApp de muestra en mayo de 2012 que usa JDO 3.0 y DataNucleus 3.0. Observe qué tan limpio está: https://github.com/TorbenVesterager/BadAssWebApp.

Bueno, quizás esté un poco demasiado limpio, porque uso los POJO tanto para la base de datos como para el cliente JSON, pero es divertido 🙂

PD: contiene algunas anotaciones SuppressWarnings (desarrolladas en IntelliJ 11)