Запись в классе помощника Jooq.(Как только я это выясню, будет добавлено больше специфических для бизнеса методов ...)
import org.jooq.*
import org.springframework.stereotype.Repository
import javax.inject.Inject
import javax.inject.Provider
/**A helper class facilitating database manipulations.
* Uses jOOQ for its manipulations.
* Relies on the application context being properly initialized s.t. Spring creates and injects the correct
* [DSLContext].*/
@Repository
class DatabaseManipulator{
private val provider: Provider<DSLContext>
private val create:DSLContext
get() = provider.get()
@Inject
constructor(provider: Provider<DSLContext>) {
this.provider = provider
}
/**Executes non-[Select]-type SQL queries on the database.
* Does not perform any kind of checks and trusts the client to know what they're doing.
* @param query the query to be executed.
*
* @return depending on the type of the [query]:
* <ul>
* <li> Delete : the number of deleted records</li>
* <li> Insert : the number of inserted records</li>
* <li> Merge : result may be meaningless</li>
* <li> Truncate : result may be meaningless</li>
* <li> Update : the number of updated records</li>
* </ul>
*/
fun execute(query:DSLContext.()-> Query):Int{
return create.query().execute()
}
/**Executes [Select]-type [query] and returns its result*/
fun <T:Record> execute(query:DSLContext.()->Select<T>):Result<T>{
return create.query().fetch()
}
}
Пока все хорошо.Теперь давайте добавим несколько тестов
@RunWith(SpringJUnit4ClassRunner::class)
@SpringBootTest
@Transactional
class DatabaseManipulatorIT {
@Inject
private lateinit var manipulate:DatabaseManipulator
@Inject
private lateinit var em:EntityManager
@Test
fun executeSelectQuery() {
//given
val expectedNumberOfOrganizations = em.createQuery("SELECT COUNT (o) FROM Organization o")
.singleResult as Long
//when
val reportedNumberOfOrganizations = manipulate.execute {
selectCount().from(ORGANIZATION)
}.first().value1().toLong()
//then
assertThat(reportedNumberOfOrganizations).isEqualTo(expectedNumberOfOrganizations)
}
@Test
fun executeNonSelectQuery() {
//given
val expectedNumberOfDeletions = em.createQuery(
"SELECT COUNT (o) FROM Organization o WHERE o.usageCreditLimited = true"
).singleResult as Long
//when
val actualNumberOfDeletions = manipulate.execute {(
deleteFrom(ORGANIZATION)
.where(ORGANIZATION.USAGECREDITLIMITED.eq(true))
) as Query
}
//then
assertThat(actualNumberOfDeletions).isEqualTo(expectedNumberOfDeletions)
}
}
Не удается скомпилировать, потому что
Error:(50, 50) Kotlin: Type inference failed: fun <T : Record> execute(query: DSLContext.() -> Select<T>): Result<T>
cannot be applied to
(DSLContext.() -> DeleteConditionStep<OrganizationRecord!>!)
Error:(50, 58) Kotlin: Type mismatch: inferred type is DSLContext.() -> DeleteConditionStep<OrganizationRecord!>! but DSLContext.() -> Select<???> was expected
Не дерьмо, я не хочу , чтобы вы использовали этот метод, я хочуиспользовать other .
Давайте попробуем сделать это явным:
//when
val actualNumberOfDeletions = manipulate.execute {(
deleteFrom(ORGANIZATION)
.where(ORGANIZATION.USAGECREDITLIMITED.eq(true))
) as Query
}
все еще не удается скомпилировать второй тестовый пример, потому что
Error:(50, 50) Kotlin: Type inference failed: fun <T : Record> execute(query: DSLContext.() -> Select<T>): Result<T>
cannot be applied to
(DSLContext.() -> Query)
Error:(50, 58) Kotlin: Type mismatch: inferred type is DSLContext.() -> Query but DSLContext.() -> Select<???> was expected
Как мне заставить Котлина вызвать правильный метод?