Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eager fetching, collections, and detaching objects from the transaction #374

Closed
v79 opened this issue Aug 25, 2018 · 2 comments
Closed

Eager fetching, collections, and detaching objects from the transaction #374

v79 opened this issue Aug 25, 2018 · 2 comments

Comments

@v79
Copy link

v79 commented Aug 25, 2018

I think I might be about to give up on Exposed and scurry back to Hibernate. I'm trying to fetch a complete object graph but without eager fetching of collections, I don't know how to do it. I'm assuming a three-layer separation of concerns - a web layer, a service layer, and a DB/DAO layer. My service layer wants to convert the DB/DAO objects (like PageTemplates below) into a viewable web layer model. Where should my transaction blocks be? In the DAO, or in the service layer?

Given this model:

object PAGE_TEMPLATE : LongIdTable() {
	val refName = varchar("ref_name", 255).uniqueIndex()
}
object INPUT_FIELD : LongIdTable() {
	val refName = varchar("ref_name", 255).uniqueIndex()
	val pageTemplate = optReference("page_template", PAGE_TEMPLATE)
}
class InputFields(id: EntityID<Long>) : LongEntity(id) {
	var refName by INPUT_FIELD.refName
	var pageTemplate by PageTemplates optionalReferencedOn INPUT_FIELD.pageTemplate
	companion object : LongEntityClass<InputFields>(INPUT_FIELD)
}
class PageTemplates(id: EntityID<Long>) : LongEntity(id) {
	var refName by PAGE_TEMPLATE.refName
	val fields by InputFields optionalReferrersOn INPUT_FIELD.pageTemplate
	companion object : LongEntityClass<PageTemplates>(PAGE_TEMPLATE) {
		fun get(refName: String): PageTemplates? { .... ] }
}

I want to write the get(refName: String) function which will return an entire PageTemplate object, including all of its fields, eagerly fetched and ready to be sent up to the service layer as a detached object.

fun get(refName: String): PageTemplates? {
	var template: PageTemplates? = null
	transaction(dbConnections.connect()) {
		addLogger(StdOutSqlLogger)
		// there will only be one matching PAGE_TEMPLATE to this query, but multiple rows because there are many INPUT_FIELDS belonging to the template
		val result = PAGE_TEMPLATE.innerJoin(INPUT_FIELD).select {
			PAGE_TEMPLATE.refName eq refName and (INPUT_FIELD.pageTemplate eq PAGE_TEMPLATE.id)
		}.toList()				
		if (result != null) {
			template = wrapRows(result)		// type mismatch error here
		}
	}
	return template
}

Maybe I'm completely misunderstanding Exposed, but my gut feeling is that an ORM should allow me to do this. As it is, I feel as though I have to write a getPageTemplate(refName) function, a getInputFieldsForTemplate(refName) function, and and many more besides, at both the service and DAO layers. And that doesn't feel very ORM to me.

@Tapac
Copy link
Contributor

Tapac commented Aug 26, 2018

Related issue #281

@Tapac
Copy link
Contributor

Tapac commented Mar 9, 2019

@v79 , Why do you use wrapRows (which returns an Iterable) and try to assign it to an object reference?
You have to use one of the following:

fun get(refName: String): PageTemplates? {
	return transaction(dbConnections.connect()) {
		addLogger(StdOutSqlLogger)		
		wrapRows(PAGE_TEMPLATE.innerJoin(INPUT_FIELD).select {
			PAGE_TEMPLATE.refName eq refName and (INPUT_FIELD.pageTemplate eq PAGE_TEMPLATE.id)
		}).firstOrNull()				
	}
}

or

fun get(refName: String): PageTemplates? {
	return transaction(dbConnections.connect()) {
		addLogger(StdOutSqlLogger)		
		PAGE_TEMPLATE.innerJoin(INPUT_FIELD).select {
			PAGE_TEMPLATE.refName eq refName and (INPUT_FIELD.pageTemplate eq PAGE_TEMPLATE.id)
		}.firstOrNull()?.let { row ->
                    wrapRow(row)
                }				
	}
}

@Tapac Tapac closed this as completed Jun 13, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants