3 ms·
Jpa ID’s can be any serializable with a matching column type. If you’re going down to the JDBI level or doing jooq to get at your data, there’s a problem. I’ve
by gabereiser 3y ago
Jpa ID’s can be any serializable with a matching column type. If you’re going down to the JDBI level or doing jooq to get at your data, there’s a problem. I’ve found most of my issues with Jpa and Hibernate specifically are due to relationships and my table design. Sometimes just having the foreignkey and not the full relationship is the answer, sometimes writing a custom @Query is, but never has going down to the jdbc level been pleasurable. Even looking at your example above, it’s something I would flag in a code review as being not novel and not trivial and therefore complicates the code base unnecessarily. SynchronizedQuery can be simplified with the synchronized keyword in modern Java on the interface method of your repository.
For a really large spring project with hundreds of tables, we abandoned entity relationships outside of FK’s and instead did our joins in @Query’s, named queries (views essentially), services (to join repositories) and some components to share cached results in-memory, across nodes. What kind of ID were you trying to use and did you create a generator for it? IdentifierGenerator interface
- seadan83 3y ago> Even looking at your example above, it’s something I would flag in a code review as being not novel and not trivial and therefore complicates the code base unnecessarily. SynchronizedQuery can be simplified with the synchronized keyword in modern Java on the interface method of your repository. Apparently that lengthy bit of code is to specify the query space. That call to "hq.addSynchronizedEntityClass(Author.class);" is seemingly a critical part. I learned a bit though to consider whether that could be simply sychronized (I appreciate your response!) From that same blog post: >> The query space describes which entity classes your query references. Hibernate uses it to optimize the dirty check and flush operation that it has to perform before executing the query.. You can do that by unwrapping Hibernate’s SynchronizeableQuery from JPA’s Query interface and calling the addSynchronizedEntityClass method with a reference to your entity class. I agree that is not trivial and complicates the code base unnecessarily. For comparison (just putting this out there), the equivalent JDBI (with no concerns over dirty checks, flush operations, or query spaces) in nearly its entirety is : ``` List<Author> author = jdbi .withResultMapper(BeanFactoryMapper.of(Author.class)) .withHandle(handle -> handle.createQuery("select first, last from author") .mapTo(Author.class) .list()); @Data class Author { String first; String last; } ``` I particularly like how this moves so much knowledge into the query string and away from the java classes. The above could be a far more complex query with joins, aggregation functions, etc.. and no new java classes would be needed, just a longer query string. In JPA, there is no query string of course. In JPA, the complexity of a more complicated query is pushed to additional classes with data fields and annotations. This is just a different characteristic of how one scales with complexity vs the other. Whether ORM vs result-set-mapper is better depends on context. It's all about picking the right tool for the right job. There are difference in how they scale relative to needed queries, complexity of data model, it's very situational. As an analogy, I think ORM is like PHP - great for getting started and building some pretty big stuff very quickly. For a larger system I would not recommend PHP. I find JPA to be very hard to maintain once scaled to larger code bases with non-trivial relational data. > What kind of ID were you trying to use and did you create a generator for it? IdentifierGenerator interface It was a vanilla Long. The IdentifierGenerator suggestion is a good one, I think that might have solved potentially all of the problems we had with the PK values (there were others). I think the crux of that issue was the existing annotation worked, but then we also needed it to work for a very ancient version of Oracle where it no longer. The required annotations for the two different versions of Oracle were not compatible with one another.. just messy. The issue of 'sometimes eager fetch' vs 'sometimes lazy fetch' was a large problem at the same time. I think that was perhaps a difficult problem because an '@Eager' was added to a number of fields already so teasing these different scenarios apart for all of the existing queries involving a number of entities was going to be a very non-trivial process. ------------- I'm just pointing out there are trade-offs when going with an ORM vs a result-set mapper. Both are better than doing some direct JDBC work. Spring+JPA pushes you into an ORM philosophy, which still for sure has its place.
- gabereiser 3y agoI agree with you. ORM is for business domain object that you know of, are certain of, have clear definition of, and are the core data structures for your app. If you have to explore data in unintended ways, result-set mapper is useful. Another option is to provide an analysis tool that weaves into your app allowing you to run result-set mapper queries against your data source without having to make it part of your data access strategy in your application. Just a thought. Spring+JPA is designed for business, boring relational business, 99% of the time.