Friday, March 12, 2021

Re: New Article "10 Best Java Frameworks to Use in 2021"

No one mentioned proxy issues with Hibernate. Am I the only one who suffers from that? Basically with those proxies you never know if your code will actually work in production because Hibernate sometimes returns proxies sometimes it does not. I have even seen (though years ago) a mix of proxies and non-proxies in the same result set. Since we've started to use inheritance extensively in our persistence entities we face issues with Hibernate proxies where standard Java approach to check "instanceof" don't work. So we have to introduce special "instance of" method and don't forget to deproxy entity before casting it to a subclass. This means that Java compiler is not able to catch bugs when such special "instanceof" and deproxying is not used. Hibernate supports byte code entity enhancing as a replacement for default usage of Hibernate proxies but we are not able to configure byte-code enhancement to work properly. For example, the same query that returns single entity with several joined entities produces just one additional query without byte-code enhancement and produces  23 additional queries with byte-code enhancement. I would have never chosen Hibernate and JPA again for several reasons. Here is another one. If code changes a property of a persistence entity you have to know if it is detached or not, depending on situation if you want the change to be propagated to DB or you just updating it for a view. So I have come to conclusion that all  the classes that use Hibernate / JPA should be hidden behind some interface and not to leak its issues to the rest of application. And those interfaces should never ever return any JPA persistence entities. And all business logic should not be in those persistence entities which means these are just shallow ORM entities.
On Thursday, March 11, 2021 at 2:27:52 PM UTC-5 t.br...@gmail.com wrote:
On Thursday, March 11, 2021 at 3:39:37 PM UTC+1 Luis Fernando Planella Gonzalez wrote:
We use JPA with EclipseLink. Gave us a lot better performance than Hibernate when we compared both.
The thing I like more with ORMs is that they are class-first. One creates the entity, annotates it correctly and generate the schema.

Ah yes, that's also one of those things I dislike about JPA 😊
And retrofitting JPA on an existing schema is… not easy (or leads to non-idiomatic entities). Fortunately I've only had to do that twice I think.
Many performance issues I've seen had to do with databases when doing complex queries, so in addition to not fully controlling your SQL queries, you also don't fully control the schema; or maybe more accurately you have to learn how each JPA mapping strategy translates to SQL.
Unless I'm mistaken, this also leads to putting zero or very few "check constraints" in the database (i.e. besides not null, unique constraints and referential integrity). Lately I've used exclusion constraints in Postgres (https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-EXCLUSION) to handle complex uniqueness or non-overlapping date ranges, and other check constraints for some things others would likely implement as "business rules" in the application (things like "if that enum field's value is A then this other field must be null, and otherwise then it must be non-null and positive", or simpler things like "only one of those 2 fields can be null at a time", and in some cases they must not both be null).
 
For those liking a schema-first approach, I like a lot the Querydsl project. It is not as active nowadays as it used to be, but is very nice.
And works both for plain SQL and JPA (I HATE with passion the JPA criteria queries, Querydsl is so much more readable). 

Querydsl is quite similar to jOOQ (which can generate code from JPA entities too: https://www.jooq.org/doc/3.14/manual/code-generation/codegen-jpa/), although less "integrated" with JPA: https://www.jooq.org/doc/3.14/manual/sql-execution/alternative-execution-models/using-jooq-with-jpa/
jOOQ will always do native SQL though, whereas Querydsl will use JPQL (or similar).
 
It gives us typed queries and is very extensible. You can even define your own extensions as annotated static methods and it generates those as methods in the metamodel, so things like these are possible:

This is interesting.
I've used extension methods in a Kotlin project, that alleviates the need for such a feature; but with Java indeed one would have to write isActive(p) without that.
I'm actually not sure what I prefer.

(fwiw, JPA Criteria with JPA Metamodel in JPA 2.0 also gives you typed queries; the API still is 🤢)
 

// Q* are the generated classes for the Querydsl metamodel
QPerson p = QPerson.person;
List<Person> admins = query
    .select(p)
    .from(p)
    .where(
        p.role.eq(Role.ADMIN),
        p.isActive()) // This would be a custom method via extension
    .orderBy(p.name.asc())
    .fetch();

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-web-toolkit/6711bec4-4772-42e7-8574-08a406a5f2acn%40googlegroups.com.

No comments:

Post a Comment