Database • Focus OOP, not Relational Database • No matter of RDBMS vendor - Same code • Hibernate coverage is 95% over traditional SQL statements • ORM not suitable for data centric application in performance • Why should you use an ORM?
OOP • No need to know relations and constraints of entities • No need to know specific DB features by various vendor • No need to know SQL, just use Java API • Supplement by HQL or JPQL or QueryDSL • All support for Stateful, Stateless (Default is Stateful)
is wired • Hard to learning (exponential) • Low performance by stateful and fetch by id • No suitable for Bulk or Set operations • Massive Insert, Statistical Summary (Cube …) • Non-Threadsafe Session - Low throughput • Need to learn specific JPA Vendor (Hibernate, Eclipse Link) • HQL, @DynamicInsert, @LazyCollection • 2nd Cache (recommend JCache (JSR-305))
override (hashCode, equals, toString) • No using @NatualId • Bad Policy / Bad Design • Every entity has Own identifier (Some case no need) • Poor performance -> Mislead “JPA is bad” • Apply not suitable case • Bulk operations, Statistical operations • No use supplement features • StatelessSession, 2nd Cache …
based, Support Multi DB Vendor • No need stateful for Reference object • Support association, inheritance, converter in JPA • Performance • Speed up like Plain SQL • Stateless • Support Asynchronous or Reactive • Support Bulk or Batch operations
Relational Mapping • Bring relational model to Scala OOP • Natural fit ( no impedance mismatch) • Stateless • Matures (Slick version 3) (Non-blocking DBIO) • Essential Slick Book
• Fast startup & performance • Schema generation • Blocking / Non-blocking API (Reactive with RxJava) • Support partial object / refresh / upsert • Custom type converter like JPA • Compile time entity validation • Support almost JPA annotations
Provide two layers of data access • Typesafe SQL wrapping DSL • Lightweight Data Access Object • See : First steps with Kotlin/Exposed • Cons • Not support parameterized SQL
Cities.name) .select { (Users.id.eq("andrey") or Users.name.eq("Sergey")) and Users.id.eq("sergey") and Users.cityId.eq(Cities.id) } .forEach { println("${it[Users.name]} lives in ${it[Cities.name]}") }
= varchar("name", 50).index() val city = reference("city", Cities) val age = integer("age") } object Cities: IntIdTable() { val name = varchar("name", 50) } Schema Definition class User(id: EntityID<Int>) : IntEntity(id){ companion object : IntEntityClass<User>(Users) var name by Users.name var city by City referencedOn Users.city var age by Users.age } class City(id: EntityID<Int>) : IntEntity(id) { companion object : IntEntityClass<City>(Cities) var name by Cities.name val users by User referrersOn Users.city } Entity Definition
= "Munich" } User.new { name = "a" city = munich age = 5 } User.new { name = "b" city = munich age = 27 } munich.users.joinToString { it.name } User.find { Users.age.between(18, 60) } One To Many All user’s name in Munich
• jOOQ or requery • Scala only ? -> Slick • Kotlin only ? -> requery, Exposed • No matter language? -> requery • Need Reactive programming? -> • requery with kotlinx-requery • kotlinx-rxjava2-jdbc ( we will open March )