Skip to content

Commit 8bfef72

Browse files
committed
Update the hibernate example: bump hibernate to 7.4.4.Final, add JPA plugin, replace xml config with code config, some other fixes
1 parent 3f33063 commit 8bfef72

10 files changed

Lines changed: 86 additions & 180 deletions

File tree

examples/projects/dev/hibernate/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
plugins {
22
alias(libs.plugins.kotlin.jvm)
33
alias(libs.plugins.kotlin.dataframe)
4+
alias(libs.plugins.kotlin.jpa)
45
alias(libs.plugins.ktlint.gradle)
56

67
application

examples/projects/dev/hibernate/gradle/libs.versions.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ dataframe = "1.0.0-Beta5"
44
ktlint-gradle = "14.0.1"
55
ktlint = "1.8.0"
66
h2db = "2.4.240"
7-
hibernate = "7.3.7.Final"
7+
hibernate = "7.4.4.Final"
88
hikari = "7.0.2"
99
sl4j = "2.0.17"
1010

@@ -22,3 +22,5 @@ ktlint-gradle = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint-gr
2222

2323
# The Kotlin DataFrame Compiler plugin is the same version as the Kotlin plugin.
2424
kotlin-dataframe = { id = "org.jetbrains.kotlin.plugin.dataframe", version.ref = "kotlin" }
25+
26+
kotlin-jpa = { id = "org.jetbrains.kotlin.plugin.jpa", version.ref = "kotlin" }

examples/projects/dev/hibernate/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/hibernate/entities.kt

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ package org.jetbrains.kotlinx.dataframe.examples.hibernate
22

33
import jakarta.persistence.Column
44
import jakarta.persistence.Entity
5+
import jakarta.persistence.FetchType
56
import jakarta.persistence.GeneratedValue
67
import jakarta.persistence.GenerationType
78
import jakarta.persistence.Id
9+
import jakarta.persistence.JoinColumn
10+
import jakarta.persistence.ManyToOne
811
import jakarta.persistence.Table
912
import org.jetbrains.kotlinx.dataframe.annotations.ColumnName
1013
import org.jetbrains.kotlinx.dataframe.annotations.DataSchema
@@ -17,9 +20,10 @@ class AlbumsEntity(
1720
@Column(name = "AlbumId")
1821
var albumId: Int? = null,
1922
@Column(name = "Title", length = 160, nullable = false)
20-
var title: String = "",
21-
@Column(name = "ArtistId", nullable = false)
22-
var artistId: Int = 0,
23+
var title: String,
24+
@ManyToOne(fetch = FetchType.LAZY, optional = false)
25+
@JoinColumn(name = "ArtistId", nullable = false)
26+
var artist: ArtistsEntity,
2327
)
2428

2529
@Entity
@@ -30,7 +34,7 @@ class ArtistsEntity(
3034
@Column(name = "ArtistId")
3135
var artistId: Int? = null,
3236
@Column(name = "Name", length = 120, nullable = false)
33-
var name: String = "",
37+
var name: String,
3438
)
3539

3640
@Entity
@@ -41,9 +45,9 @@ class CustomersEntity(
4145
@Column(name = "CustomerId")
4246
var customerId: Int? = null,
4347
@Column(name = "FirstName", length = 40, nullable = false)
44-
var firstName: String = "",
48+
var firstName: String,
4549
@Column(name = "LastName", length = 20, nullable = false)
46-
var lastName: String = "",
50+
var lastName: String,
4751
@Column(name = "Company", length = 80)
4852
var company: String? = null,
4953
@Column(name = "Address", length = 70)
@@ -61,7 +65,7 @@ class CustomersEntity(
6165
@Column(name = "Fax", length = 24)
6266
var fax: String? = null,
6367
@Column(name = "Email", length = 60, nullable = false)
64-
var email: String = "",
68+
var email: String,
6569
@Column(name = "SupportRepId")
6670
var supportRepId: Int? = null,
6771
)

examples/projects/dev/hibernate/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/hibernate/main.kt

Lines changed: 28 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ import jakarta.persistence.criteria.CriteriaDelete
55
import jakarta.persistence.criteria.CriteriaQuery
66
import jakarta.persistence.criteria.Root
77
import org.hibernate.FlushMode
8+
import org.hibernate.Session
89
import org.hibernate.SessionFactory
9-
import org.hibernate.cfg.Configuration
10+
import org.hibernate.hikaricp.internal.HikariCPConnectionProvider
11+
import org.hibernate.jpa.HibernatePersistenceConfiguration
12+
import org.hibernate.tool.schema.Action
1013
import org.jetbrains.kotlinx.dataframe.DataFrame
1114
import org.jetbrains.kotlinx.dataframe.DataRow
1215
import org.jetbrains.kotlinx.dataframe.api.asSequence
@@ -43,17 +46,16 @@ fun main() {
4346
}
4447

4548
private fun SessionFactory.insertSampleData() {
46-
withTransaction { session ->
49+
inTransaction { session ->
4750
// a few artists and albums (minimal, not used further; just demo schema)
4851
val artist1 = ArtistsEntity(name = "AC/DC")
4952
val artist2 = ArtistsEntity(name = "Queen")
5053
session.persist(artist1)
5154
session.persist(artist2)
52-
session.flush()
5355

54-
session.persist(AlbumsEntity(title = "High Voltage", artistId = artist1.artistId!!))
55-
session.persist(AlbumsEntity(title = "Back in Black", artistId = artist1.artistId!!))
56-
session.persist(AlbumsEntity(title = "A Night at the Opera", artistId = artist2.artistId!!))
56+
session.persist(AlbumsEntity(title = "High Voltage", artist = artist1))
57+
session.persist(AlbumsEntity(title = "Back in Black", artist = artist1))
58+
session.persist(AlbumsEntity(title = "A Night at the Opera", artist = artist2))
5759
// customers we'll analyze using DataFrame
5860
session.persist(
5961
CustomersEntity(
@@ -89,15 +91,15 @@ private fun SessionFactory.loadCustomersAsDataFrame(): DataFrame<DfCustomers> =
8991
val root: Root<CustomersEntity> = criteriaQuery.from(CustomersEntity::class.java)
9092
criteriaQuery.select(root)
9193

92-
session.createQuery(criteriaQuery)
94+
session.createSelectionQuery(criteriaQuery)
9395
.resultList
9496
.map { c ->
9597
DfCustomers(
9698
address = c.address,
9799
city = c.city,
98100
company = c.company,
99101
country = c.country,
100-
customerId = c.customerId ?: -1,
102+
customerId = c.customerId ?: error("Loaded customer must have a generated id"),
101103
email = c.email,
102104
fax = c.fax,
103105
firstName = c.firstName,
@@ -118,7 +120,7 @@ private fun SessionFactory.loadCustomersAsDataFrame(): DataFrame<DfCustomers> =
118120
}
119121

120122
/** DTO used for aggregation projection. */
121-
private data class CountryCountDto(val country: String, val customerCount: Long)
123+
private data class CountryCountDto(val country: String?, val customerCount: Long)
122124

123125
/**
124126
* **Hibernate + Criteria API:**
@@ -132,9 +134,8 @@ private fun SessionFactory.countCustomersPerCountryWithHibernate() {
132134
val cb = session.criteriaBuilder
133135
val cq: CriteriaQuery<CountryCountDto> = cb.createQuery(CountryCountDto::class.java)
134136
val root: Root<CustomersEntity> = cq.from(CustomersEntity::class.java)
135-
136-
val countryPath = root.get<String>("country")
137-
val idPath = root.get<Long>("customerId")
137+
val countryPath = root.get<String?>("country")
138+
val idPath = root.get<Int?>("customerId")
138139

139140
val countExpr = cb.count(idPath)
140141

@@ -148,7 +149,7 @@ private fun SessionFactory.countCustomersPerCountryWithHibernate() {
148149
cq.groupBy(countryPath)
149150
cq.orderBy(cb.desc(countExpr))
150151

151-
val results = session.createQuery(cq).resultList
152+
val results = session.createSelectionQuery(cq).resultList
152153
results.forEach { dto ->
153154
println("${dto.country}: ${dto.customerCount} customers")
154155
}
@@ -175,22 +176,18 @@ private fun DataFrame<DfCustomers>.analyzeAndPrintResults() {
175176
.print(columnTypes = true, borders = true)
176177
}
177178

178-
private fun SessionFactory.replaceCustomersFromDataFrame(df: DataFrame<DfCustomers>) {
179-
withTransaction { session ->
179+
private fun SessionFactory.replaceCustomersFromDataFrame(df: DataFrame<DfCustomers>) =
180+
inTransaction { session ->
180181
val criteriaBuilder: CriteriaBuilder = session.criteriaBuilder
181182
val criteriaDelete: CriteriaDelete<CustomersEntity> =
182183
criteriaBuilder.createCriteriaDelete(CustomersEntity::class.java)
183184
criteriaDelete.from(CustomersEntity::class.java)
184-
185185
session.createMutationQuery(criteriaDelete).executeUpdate()
186-
}
187186

188-
withTransaction { session ->
189187
df.asSequence().forEach { row ->
190188
session.persist(row.toCustomersEntity())
191189
}
192190
}
193-
}
194191

195192
private fun DataRow<DfCustomers>.toCustomersEntity(): CustomersEntity =
196193
CustomersEntity(
@@ -209,40 +206,21 @@ private fun DataRow<DfCustomers>.toCustomersEntity(): CustomersEntity =
209206
supportRepId = this.supportRepId,
210207
)
211208

212-
private inline fun <T> SessionFactory.withSession(block: (session: org.hibernate.Session) -> T): T =
213-
openSession().use(block)
214-
215-
private inline fun SessionFactory.withTransaction(block: (session: org.hibernate.Session) -> Unit) {
216-
withSession { session ->
217-
session.beginTransaction()
218-
try {
219-
block(session)
220-
session.transaction.commit()
221-
} catch (e: Exception) {
222-
session.transaction.rollback()
223-
throw e
224-
}
225-
}
226-
}
227-
228209
/** Read-only transaction helper for SELECT queries to minimize overhead. */
229-
private inline fun <T> SessionFactory.withReadOnlyTransaction(block: (session: org.hibernate.Session) -> T): T =
230-
withSession { session ->
231-
session.beginTransaction()
210+
private inline fun <T> SessionFactory.withReadOnlyTransaction(crossinline block: (session: Session) -> T): T =
211+
fromTransaction { session ->
232212
// Minimize overhead for read operations
233213
session.isDefaultReadOnly = true
234214
session.hibernateFlushMode = FlushMode.MANUAL
235-
try {
236-
val result = block(session)
237-
session.transaction.commit()
238-
result
239-
} catch (e: Exception) {
240-
session.transaction.rollback()
241-
throw e
242-
}
215+
block(session)
243216
}
244217

245-
private fun buildSessionFactory(): SessionFactory {
246-
// Load configuration from resources/hibernate/hibernate.cfg.xml
247-
return Configuration().configure("hibernate/hibernate.cfg.xml").buildSessionFactory()
248-
}
218+
private fun buildSessionFactory(): SessionFactory = HibernatePersistenceConfiguration("hibernate-example")
219+
.managedClasses(CustomersEntity::class.java, ArtistsEntity::class.java, AlbumsEntity::class.java)
220+
.jdbcUrl("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1")
221+
.jdbcCredentials("sa", "")
222+
.schemaToolingAction(Action.CREATE_DROP)
223+
.showSql(true, true, true)
224+
.property("hibernate.connection.provider_class", HikariCPConnectionProvider::class.java)
225+
.property("hibernate.hikari.maximumPoolSize", 5)
226+
.createEntityManagerFactory()

examples/projects/dev/hibernate/src/main/resources/hibernate/hibernate.cfg.xml

Lines changed: 0 additions & 32 deletions
This file was deleted.

examples/projects/hibernate/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
plugins {
22
alias(libs.plugins.kotlin.jvm)
33
alias(libs.plugins.kotlin.dataframe)
4+
alias(libs.plugins.kotlin.jpa)
45
alias(libs.plugins.ktlint.gradle)
56

67
application

examples/projects/hibernate/gradle/libs.versions.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ dataframe = "1.0.0-Beta5"
44
ktlint-gradle = "14.0.1"
55
ktlint = "1.8.0"
66
h2db = "2.4.240"
7-
hibernate = "7.3.7.Final"
7+
hibernate = "7.4.4.Final"
88
hikari = "7.0.2"
99
sl4j = "2.0.17"
1010

@@ -22,3 +22,5 @@ ktlint-gradle = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint-gr
2222

2323
# The Kotlin DataFrame Compiler plugin is the same version as the Kotlin plugin.
2424
kotlin-dataframe = { id = "org.jetbrains.kotlin.plugin.dataframe", version.ref = "kotlin" }
25+
26+
kotlin-jpa = { id = "org.jetbrains.kotlin.plugin.jpa", version.ref = "kotlin" }

examples/projects/hibernate/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/hibernate/entities.kt

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ package org.jetbrains.kotlinx.dataframe.examples.hibernate
22

33
import jakarta.persistence.Column
44
import jakarta.persistence.Entity
5+
import jakarta.persistence.FetchType
56
import jakarta.persistence.GeneratedValue
67
import jakarta.persistence.GenerationType
78
import jakarta.persistence.Id
9+
import jakarta.persistence.JoinColumn
10+
import jakarta.persistence.ManyToOne
811
import jakarta.persistence.Table
912
import org.jetbrains.kotlinx.dataframe.annotations.ColumnName
1013
import org.jetbrains.kotlinx.dataframe.annotations.DataSchema
@@ -17,9 +20,10 @@ class AlbumsEntity(
1720
@Column(name = "AlbumId")
1821
var albumId: Int? = null,
1922
@Column(name = "Title", length = 160, nullable = false)
20-
var title: String = "",
21-
@Column(name = "ArtistId", nullable = false)
22-
var artistId: Int = 0,
23+
var title: String,
24+
@ManyToOne(fetch = FetchType.LAZY, optional = false)
25+
@JoinColumn(name = "ArtistId", nullable = false)
26+
var artist: ArtistsEntity,
2327
)
2428

2529
@Entity
@@ -30,7 +34,7 @@ class ArtistsEntity(
3034
@Column(name = "ArtistId")
3135
var artistId: Int? = null,
3236
@Column(name = "Name", length = 120, nullable = false)
33-
var name: String = "",
37+
var name: String,
3438
)
3539

3640
@Entity
@@ -41,9 +45,9 @@ class CustomersEntity(
4145
@Column(name = "CustomerId")
4246
var customerId: Int? = null,
4347
@Column(name = "FirstName", length = 40, nullable = false)
44-
var firstName: String = "",
48+
var firstName: String,
4549
@Column(name = "LastName", length = 20, nullable = false)
46-
var lastName: String = "",
50+
var lastName: String,
4751
@Column(name = "Company", length = 80)
4852
var company: String? = null,
4953
@Column(name = "Address", length = 70)
@@ -61,7 +65,7 @@ class CustomersEntity(
6165
@Column(name = "Fax", length = 24)
6266
var fax: String? = null,
6367
@Column(name = "Email", length = 60, nullable = false)
64-
var email: String = "",
68+
var email: String,
6569
@Column(name = "SupportRepId")
6670
var supportRepId: Int? = null,
6771
)

0 commit comments

Comments
 (0)