I have the following DAO classes
package exposed.example
import org.jetbrains.exposed.dao.EntityID
import org.jetbrains.exposed.dao.UUIDEntity
import org.jetbrains.exposed.dao.UUIDEntityClass
import org.jetbrains.exposed.dao.UUIDTable
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.transactions.transaction
import java.util.*
object CustomerTable: UUIDTable(name = "customer") {
val name = varchar(name = "name", length = 255).uniqueIndex()
}
class CustomerDAO(id: EntityID<UUID>): UUIDEntity(id) {
companion object : UUIDEntityClass<CustomerDAO>(CustomerTable)
var name by CustomerTable.name
}
object OrderTable: UUIDTable(name = "orders") {
val customer = reference(name = "customer_id", foreign = CustomerTable)
val product = varchar(name = "product", length = 255)
}
class OrderDAO(id: EntityID<UUID>): UUIDEntity(id) {
companion object : UUIDEntityClass<OrderDAO>(OrderTable)
var customer by OrderTable.customer
var product by OrderTable.product
}
If I create transaction manually then entities got persisted in the database, see the code below
fun main(args: Array<String>) {
Database.connect("jdbc:postgresql://localhost:5432/testdb", driver = "org.postgresql.Driver", user = "test", password = "testpassword")
transaction {
SchemaUtils.create(CustomerTable, OrderTable)
val customer = CustomerDAO.new {
name = "Alice_${System.currentTimeMillis()}"
}
OrderDAO.new {
this.customer = customer.id
product = "MegaProduct"
}
}
}
But if I use the same CustomerDAO
and OrderDAO
in a @Transactional method in spring boot app, strange things are starting to happen.
package exposed.example
import org.jetbrains.exposed.spring.SpringTransactionManager
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
import org.springframework.transaction.annotation.EnableTransactionManagement
import org.springframework.transaction.annotation.Transactional
import javax.sql.DataSource
open class Service {
@Transactional
open fun createCustomer(name: String): CustomerDAO {
return CustomerDAO.new {
this.name = name
}
}
@Transactional
open fun createOrder(customer: CustomerDAO, product: String): OrderDAO {
return OrderDAO.new {
this.customer = customer.id
this.product = product
}
}
@Transactional
open fun doBoth(name: String, product: String): OrderDAO {
return createOrder(createCustomer(name), product)
}
}
@SpringBootApplication
@EnableTransactionManagement
open class App {
@Bean
open fun transactionManager(dataSource: DataSource) = SpringTransactionManager(dataSource)
@Bean // PersistenceExceptionTranslationPostProcessor with proxyTargetClass=false, see https://github.com/spring-projects/spring-boot/issues/1844
open fun persistenceExceptionTranslationPostProcessor() = PersistenceExceptionTranslationPostProcessor()
@Bean
open fun service() = Service()
}
fun main(args: Array<String>) {
val app = runApplication<App>(*args)
val service = app.getBean(Service::class.java)
// val customer = service.createCustomer("Alice1")
// service.createOrder(customer, "SpringProduct")
service.doBoth("Bob", "SpringProduct")
}
Only customer
is created but not the order
in this case. If I uncomment two lines above then customer won't be created and the second line will cause NPE.
So in @Transactional method the entity gets persisted only if referenced by another or queried.
How to make it to be persisted anyway?
Thanks in advance,
the problem is gone in exposed 0.10.2