Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[SnowOne 2025] Михаил Поливаха: One ORM to Rule...

[SnowOne 2025] Михаил Поливаха: One ORM to Rule Them All

В современном мире достаточно много ORM-систем, с которыми, потенциально, можно работать при взаимодействии с БД. Эти ORM-решения основаны на определенных принципах, где последние определяют дизайн и ограничения той или иной системы. Мы рассмотрим различные ORM-системы, ключевые дизайн-принципы, которые они исповедуют, вытекающие из этого ограничения и возможности и, конечно, потенциальные use-кейсы.

Видео: https://youtu.be/KMui4CQ6n1E

Avatar for jugnsk

jugnsk

May 08, 2025
Tweet

More Decks by jugnsk

Other Decks in Programming

Transcript

  1. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 { Jimmer, Hibernate, Mybatis, SDJ } [One ORM to Rule Them All] Mikhail Polivakha SnowOne
  2. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 01 Hibernate, Mybatis, Jimmer, Spring Data JDBC What ORMs exists on the market 02 What are the core design principles of these frameworks 03 When it makes sense to use them Table Of ‘Contents’ { } Mikhail Polivakha SnowOne
  3. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Mikhail Polivakha • Senior Software Engineer • Spring Aio Community Board Member • Technical Writer on Baeldung • Open Source committer • Conference Speaker Mikhail Polivakha SnowOne
  4. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 01 { [Spring Data JDBC] } Mikhail Polivakha SnowOne Spring Data JDBC
  5. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 DDD is the king, and we make an assumption that we can operate with our database entities as with a bunch of aggregates As simple as possible (No caching, almost no proxying, no session/context, etc.) Principle < /2 > { Principle < /1 > { Spring Data JDBC Mikhail Polivakha SnowOne } }
  6. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 ManyToX just breaks the model. It just does not fit it. We try to be faster. Because there are fewer layers of abstraction, SDJ may beat the traditional (i.e. Stateful session) Hibernate Principle < /4 > { Principle < /3 > { } } Mikhail Polivakha SnowOne Spring Data JDBC
  7. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Spring Data JDBC
  8. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 INSERT INTO post(title, content) VALUES… INSERT INTO post_comment(body, post_id) VALUES… INSERT INTO comment_reply(content, post_comment_id) VALUES… Spring Data JDBC
  9. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 INSERT INTO post(title, content) VALUES… INSERT INTO post_comment(body, post_id) VALUES… INSERT INTO comment_reply(content, post_comment_id) VALUES… Spring Data JDBC
  10. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Spring Data JDBC Do we own this reference?
  11. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Spring Data JDBC Do we own this reference? • Reference inside aggregate? Yes • Reference outside aggregate? No
  12. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Spring Data JDBC Do we own this reference? • Reference inside aggregate? Yes • Reference outside aggregate? No
  13. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Spring Data JDBC Do we own this reference? • Reference inside aggregate? Yes • Reference outside aggregate? No Solution: Use strict boundaries
  14. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Demo { Time; Spring Data JDBC Mikhail Polivakha } SnowOne
  15. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Spring Data JDBC The Reality • Is that really impossible to implement @ManyToX? - No, absolutely not • Then why are we doing this? - Because it significantly eases the implementation
  16. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 The Good ‘Spring Data JDBC’ { } C 01 The model is simple and entities are flat C 02 The domain model fits the DDD accessing rules C 03 There is support for MyBatis Mikhail Polivakha SnowOne Spring Data JDBC
  17. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 The Bad ‘Spring Data JDBC’ { } C 01 The domain model is quite complex Spring Data JDBC Mikhail Polivakha SnowOne C 02 Still lacks some features
  18. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 The Bad ‘Spring Data JDBC’ { } C 01 The domain model is quite complex Spring Data JDBC Mikhail Polivakha SnowOne C 02 Still lacks some features ~ 18% SDJ/SDR2DBC
  19. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 02 { [Hibernate] } Mikhail Polivakha SnowOne Hibernate
  20. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 We’re reading and writing to the database entities, that are bound to a persistent context. We express our desire to interact with the database mostly via annotations on Entities (LAZY, Cascades, BatchSize) Principle < /2 > { Principle < /1 > { Hibernate Mikhail Polivakha SnowOne } }
  21. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Hibernate and JPA is designed to cover practically all possible use cases. Thus, the behavior of Hibernate is often unclear Entities represent both the schema, and the ways of accessing the data in the schema Principle < /4 > { Principle < /3 > { } } Mikhail Polivakha SnowOne Hibernate
  22. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Demo { Time; Mikhail Polivakha } SnowOne Hibernate
  23. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Hibernate Mikhail Polivakha SnowOne
  24. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Hibernate Mikhail Polivakha SnowOne
  25. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Hibernate Mikhail Polivakha SnowOne
  26. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 The Good ‘Hibernate’ { } C 01 Potentially can handle any schema whatsoever C 02 Supports the dynamic query build API via JPA’s Criteria API C 03 The queries are mostly simple and use ANSI SQL features C 04 The system can be described as OLTP and NOT High Load Hibernate Mikhail Polivakha SnowOne
  27. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 The Bad ‘Hibernate’ { } C 01 JPA can behave unpredictably C 02 Working with complex dynamic queries is challenging Mikhail Polivakha SnowOne Hibernate
  28. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 The Bad ‘Hibernate’ { } C 01 JPA can behave unpredictably Hibernate ~ 74% Hibernate C 02 Working with complex dynamic queries is challenging Mikhail Polivakha SnowOne
  29. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 03 { [MyBatis] } Mikhail Polivakha SnowOne MyBatis
  30. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Engine to generate SQL queries dynamically The Framework itself has no clear notion of an “Entity”/”Aggregate” We define our SQL and Mappers in XML or via Annotations Principle < /2 > { Principle < /1 > { MyBatis Mikhail Polivakha SnowOne } }
  31. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Typically, there is no assumption made about the result set configuration → we’re writing mappers ourselves. Principle < /3 > { MyBatis } Mikhail Polivakha SnowOne
  32. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Demo { Time; MyBatis Mikhail Polivakha } SnowOne
  33. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 The Good ‘Mybatis’ { } C 01 Fits extremely well for Complex Dynamic Queries C 02 Works great for CQRS MyBatis C 03 Transparent as it is C 04 Works great for flat result sets Mikhail Polivakha SnowOne
  34. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 The Bad ‘Mybatis’ { } C 01 Working with non-flat result sets (domain entities) becomes nearly impossible MyBatis C 02 It is just an engine for query generation -> a lot of tedious work on us C 03 MyBatis is not actively developed now Mikhail Polivakha SnowOne
  35. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 The Bad ‘Mybatis’ { } C 01 Working with non-flat result sets (domain entities) becomes nearly impossible MyBatis C 02 It is just an engine for query generation -> a lot of tedious work on us C 03 MyBatis is not actively developed now ~ 3% MyBatis Mikhail Polivakha SnowOne
  36. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 04 { [Jimmer] } Mikhail Polivakha SnowOne Jimmer
  37. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 The entities serve merely for the purpose of defining a schema For the queries themselves, we’re using constructed/generated DTO objects, rather than entities Principle < /2 > { Principle < /1 > { Jimmer Mikhail Polivakha JUGNsk } }
  38. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Because there is no Spec (like JPA) that underpins the implementation, features like caching are optional and more flexible Principle < /3 > { Jimmer } Mikhail Polivakha SnowOne
  39. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Demo { Time; Jimmer Mikhail Polivakha } SnowOne
  40. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 The Good ‘Jimmer’ { } C 01 For each query, we’re explicitly providing what we want -> the behavior of ORM framework is much clearer C 02 Can handle potentially any database schema Jimmer C 03 Tooling is impressive (DTO Generation, Kotlin DSL, auto entity-dto conversion methods) Mikhail Polivakha SnowOne
  41. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 The Bad ‘Jimmer’ { } C 01 The fundamental problems of N+1, pagination with Cartesian Product etc are still there Jimmer C 02 The framework is known to a very few people -> Very poor community Mikhail Polivakha SnowOne
  42. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 The Bad ‘Jimmer’ { } C 01 The fundamental problems of N+1, pagination with Cartesian Product etc are still there Jimmer C 02 The framework is known to a very few people -> Very poor community < 1% Jimmer Mikhail Polivakha SnowOne
  43. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Recommendations; { Should be used in case of simple schema. Consider for microservices. In case you’re ready to teach the entire team to work with a new framework, which is great btw Jimmer For most projects, this works extremely well together. Spring Data JDBC Hibernate + MyBatis } Mikhail Polivakha SnowOne
  44. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 Thank You! { } Mikhail Polivakha SnowOne