mvysny / vaadin-on-kotlin

Writing full-stack statically-typed web apps on JVM at its simplest
https://www.vaadinonkotlin.eu/
MIT License
185 stars 17 forks source link

Remove JPA #3

Closed mvysny closed 7 years ago

mvysny commented 7 years ago

This talk is hilarious: https://vimeo.com/28885655 and helped to soothe my anger a lot while fighting with Hibernate's

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.vok.Article.comments, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:582)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:201)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:561)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:132)
    at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:277)
    at kotlin.collections.CollectionsKt___CollectionsKt.joinTo(_Collections.kt:2013)
    at kotlin.collections.CollectionsKt___CollectionsKt.joinToString(_Collections.kt:2031)
    at kotlin.collections.CollectionsKt___CollectionsKt.joinToString$default(_Collections.kt:2030)
    at com.example.vok.ArticleView$refreshComments$1.invoke(ArticleView.kt:71)
    at com.example.vok.ArticleView$refreshComments$1.invoke(ArticleView.kt:16)
    at com.github.vok.framework.DBKt.db(DB.kt:146)

As it turns out, I had a detached article and there is no way of reattaching it back to the session! How dumb is that? https://stackoverflow.com/questions/912659/what-is-the-proper-way-to-re-attach-detached-objects-in-hibernate/4438358#4438358

So instead of article.comments.forEach {...} you need to write Article.find(article.id!!)!!.comments.forEach {...} to force Hibernate to reload the entity and make the bloody comments collection attached. Smooth :-1:

So there goes Hibernate. I kinda liked Ebean until I realized it needs to do some compile-time class enhancement with Maven Tiles - :-1: , sorry, no, I'm not going to install a plugin into my IDE just to develop with Ebean. There goes Ebean.

I remember EclipseLink having troubles with sequences as primary keys generators: I believe EclipseLink started with 51 instead of 1, and then EclipseLink wondered where the hell is record number 1: http://stackoverflow.com/questions/18474046/eclipselink-and-sequence-generator-preallocation :-1:

Anyway, it seems that JPA is hated by the interwebs with glaring passion: https://virgo47.wordpress.com/2014/10/09/jpa-is-it-worth-it-horror-stories-with-eclipselink-and-hibernate/ and https://www.reddit.com/r/java/comments/ln2st/jpa_the_mother_of_all_leaky_abstractions/

JPA - the mother of all leaky abstractions :-D Kinda says it all. There's no way I'm going to touch Spring Data (because it has Spring in it :-1: ), which leaves us either with (yet) another JDBC wrapper library, or https://github.com/JetBrains/Exposed . It looks quite foreign to me, but I'll evaluate.

More blogs from people pissed by Hibernate:

mvysny commented 7 years ago

Careful here: is it possible to attach JSR303 annotations to Exposed entities, and pass them around to the Vaadin Binder? Needs investigation.

mvysny commented 7 years ago

It appears that I should either adopt JPA (but switch to EclipseLink); or evaluate other options. The alternatives:

mvysny commented 7 years ago

jOOQ is nice but it needs to generate classes for a database (or you can write THREE classes per table: a TableImpl, a Record and the pojo).

mvysny commented 7 years ago

QueryDSL can not perform entity instrumentation in runtime and requires maven plugin to do so. :-1:

mvysny commented 7 years ago

MyBatis: I can't seem to find a way to just run a SELECT and map it into a POJO.

skoude commented 7 years ago

Why not use SQL2O? I'm using it in my kotlin projects and it works great...

mvysny commented 7 years ago

@skoude that is an awesome find! Thank you, I'll evaluate.

mvysny commented 7 years ago

JDBI requires you to write DAO interfaces. Maybe this can be avoided, but it's certainly not that easy :-1: http://www.sql2o.org/ looks awesome:

  1. It can map objects to results
  2. It can do inserts and deletes without having DAO interfaces
  3. Evaluate: Can it be used with HikariCP? Edit: Yes it can, via DataSource. Awesome.
skoude commented 7 years ago

Yes, SQL2O can be used with HikariCP.. I have tested it, but do not use it in production yet. SQL2O is very easy to deal with kotlin, and I like it a lot, because you can just write SQL and do not have to deal with the problems that come with JPA implementations.. It's just so simple to use. If you need some examples for using the SQL2O, just say :)

mvysny commented 7 years ago

I like it a lot, because of the simplicity it offers. I quite like how easily you can map selects to objects. Could you perhaps attach a very simple CRUD examples with a simple bean? Also, is it possible to fetch, say, a pair of objects, coming from a select join?

mvysny commented 7 years ago

@skoude which version are you using, 1.6.0-RC3?

kskyle commented 7 years ago

@mvysny I'm currently using 1.5.4, and it's working great...

kskyle commented 7 years ago

Here is a few examples of select queries.. Kotlin + SQL2o select queries

kskyle commented 7 years ago

And here is an update / insert example: Kotlin + Sql2o update or insert

mvysny commented 7 years ago

Those examples look awesome, thank you! I quite like the simplicity. I'll look at this, and perhaps port the CRUD example app to SQL2O ;)

mvysny commented 7 years ago

Too bad that SQL2O doesn't support programmatic creation of queries (other than creating the String SQL). However, looking at the horror which is JPA Criteria API, no support for such API may actually be a blessing.

kskyle commented 7 years ago

Yeap, the programmatic creation of queries is the only drawback. But when not having that we have the perfect freedom to make any kind of query we like :) But still, it could be quite easy to create an interfaces for programmatic query support for sql2o with Kotlin.. Basically we would need to check what database we are using, and then make the library so that it will use correct queries for specified database..

mvysny commented 7 years ago

True. But perhaps we can only use really simple SQL92 which should be supported by all databases. SQL92 should be more than enough for simple Grid filters.

kskyle commented 7 years ago

Yeap, that's correct. I was just thinking that it would be great to support for example postgresql json features, but that's completely other story. SQL92 dialect support would be just great.

mvysny commented 7 years ago

Javadoc is missing from nearly all Query methods; it's quite important to have javadoc there, since I have no idea how, say, Query.keys work. Other than that, it seems to work just perfectly :+1:

mvysny commented 7 years ago

Initial support for sql2o pushed into VoK. It's totally untested and rudimentary, please see MappingTest.kt for more details ;)

mvysny commented 7 years ago

Just ported the example project to sql2o. It starts way faster than with JPA/Hibernate; love it. Need to update docu.

skoude commented 7 years ago

It looks great now 👍 Will try to test it and take a deep dive into code some point at this week.

mvysny commented 7 years ago

Thanks! Done, the documentation is updated and the Getting Started guide now uses Sql2o instead of JPA: http://www.vaadinonkotlin.eu/gettingstarted.html

mvysny commented 6 years ago

I have extracted the library into an external project: https://github.com/mvysny/vok-orm This way I believe the library forms its own island which can be studied apart from VoK, and thus it can be understood much easier. Also the library can now be used even outside of VoK apps. In additional to Sql2o, the library supports:

Please try it out and let me know :)

mvysny commented 5 years ago

JDBI with API 3.0 doesn't require you to create the DAO interfaces anymore. It has a couple of dependencies totaling 1,9MB, but that's okay. It's more actively maintained than SQL2O, so maybe we should switch to that.