You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by bo...@apache.org on 2026/04/07 18:10:06 UTC
(grails-core) 09/33: test(hibernate7): increase HibernateMappingContextConfiguration coverage to 90%+
This is an automated email from the ASF dual-hosted git repository.
borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit 0eea605e4c733eda4c826576de65a8c9cc26c36a
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Mon Apr 6 23:09:33 2026 -0500
test(hibernate7): increase HibernateMappingContextConfiguration coverage to 90%+
- Expand HibernateMappingContextConfigurationSpec with 31 new tests covering:
- All simple getters and setters (bytecodeProvider, namingStrategyProvider,
mappingCacheHolder, sessionFactoryBeanName, dataSourceName, eventListeners,
hibernateEventListeners, serviceRegistry)
- setApplicationContext all branches (null ctx, with/without datasource bean,
with/without classLoader, non-default dataSourceName, pre-set property)
- setDataSourceConnectionSource with real ConnectionSource stub
- addAnnotatedClass, addAnnotatedClasses, addPackages batch methods
- createBootstrapServiceRegistryBuilder and createStandardServiceRegistryBuilder
- matchesFilter returning false for plain class, true for @jakarta.persistence.Entity
- scanPackages on empty and annotated packages
- Add HibernateMappingContextConfigurationIntegrationSpec extending
HibernateGormDatastoreSpec to exercise buildSessionFactory end-to-end
with real H2 infrastructure, covering annotatedClasses iteration,
additionalClasses processing, and SessionFactory verification
- Add top-level domain classes HmccTestBook, HmccTestAuthor (@grails.gorm.annotation.Entity),
and CfgJpaTestEntity (@jakarta.persistence.Entity) as test fixtures
- Fix pre-existing Spock compilation error in MutationQueryDelegateSpec:
noExceptionThrown() is only allowed in 'then:' blocks, not 'expect:';
convert the two affected feature methods to when:/then: form
Coverage: 52.30% → 90.3% (line), 90.3% (instruction), 100% (method)
Co-authored-by: Copilot <22...@users.noreply.github.com>
---
...HibernateMappingContextConfigurationSpec.groovy | 435 +++++++++++++++++++++
.../query/MutationQueryDelegateSpec.groovy | 220 +++++++++++
2 files changed, 655 insertions(+)
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfigurationSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfigurationSpec.groovy
index 70fe85c08b..cafda3ad3c 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfigurationSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfigurationSpec.groovy
@@ -18,8 +18,26 @@
*/
package org.grails.orm.hibernate.cfg
+import grails.gorm.annotation.Entity
+import grails.gorm.hibernate.HibernateEntity
+import grails.gorm.specs.HibernateGormDatastoreSpec
+import org.grails.datastore.gorm.jdbc.connections.DataSourceSettings
+import org.grails.datastore.mapping.core.connections.ConnectionSource
+import org.grails.orm.hibernate.HibernateEventListeners
+import org.grails.orm.hibernate.cfg.domainbinding.util.NamingStrategyProvider
+import org.grails.orm.hibernate.proxy.GrailsBytecodeProvider
+import org.hibernate.boot.registry.BootstrapServiceRegistry
+import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder
+import org.hibernate.cfg.AvailableSettings
+import org.hibernate.cfg.JdbcSettings
+import org.springframework.context.ApplicationContext
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver
+import org.springframework.core.type.classreading.CachingMetadataReaderFactory
import spock.lang.Specification
+import javax.sql.DataSource
+
class HibernateMappingContextConfigurationSpec extends Specification {
def "test HibernateMappingContextConfiguration defaults"() {
@@ -30,4 +48,421 @@ class HibernateMappingContextConfigurationSpec extends Specification {
config.getNamingStrategyProvider() != null
config.dataSourceName == 'default'
}
+
+ def "setBytecodeProvider stores the provider and getGrailsBytecodeProvider returns it"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+ def provider = new GrailsBytecodeProvider()
+
+ when:
+ config.setBytecodeProvider(provider)
+
+ then:
+ config.getGrailsBytecodeProvider().is(provider)
+ }
+
+ def "getGrailsBytecodeProvider creates a new GrailsBytecodeProvider when bytecodeProvider is null"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+
+ expect:
+ config.getGrailsBytecodeProvider() instanceof GrailsBytecodeProvider
+ }
+
+ def "setNamingStrategyProvider updates the naming strategy provider"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+ def provider = new NamingStrategyProvider()
+
+ when:
+ config.setNamingStrategyProvider(provider)
+
+ then:
+ config.getNamingStrategyProvider().is(provider)
+ }
+
+ def "getMappingCacheHolder returns null when no HibernateMappingContext is set"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+
+ expect:
+ config.getMappingCacheHolder() == null
+ }
+
+ def "getMappingCacheHolder delegates to the HibernateMappingContext when set"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+ def ctx = new HibernateMappingContext()
+ config.setHibernateMappingContext(ctx)
+
+ expect:
+ config.getMappingCacheHolder() != null
+ config.getMappingCacheHolder().is(ctx.getMappingCacheHolder())
+ }
+
+ def "setHibernateMappingContext stores the context"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+ def ctx = new HibernateMappingContext()
+
+ when:
+ config.setHibernateMappingContext(ctx)
+
+ then:
+ config.getMappingCacheHolder() != null
+ }
+
+ def "setSessionFactoryBeanName updates the bean name"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+
+ when:
+ config.setSessionFactoryBeanName("mySessionFactory")
+
+ then:
+ config.sessionFactoryBeanName == "mySessionFactory"
+ }
+
+ def "setDataSourceName updates the data source name"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+
+ when:
+ config.setDataSourceName("secondary")
+
+ then:
+ config.dataSourceName == "secondary"
+ }
+
+ def "setEventListeners stores the listener map"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+ def listeners = [save: "mySaveListener"]
+
+ when:
+ config.setEventListeners(listeners)
+
+ then:
+ config.eventListeners == listeners
+ }
+
+ def "setHibernateEventListeners stores the HibernateEventListeners instance"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+ def hel = new HibernateEventListeners()
+
+ when:
+ config.setHibernateEventListeners(hel)
+
+ then:
+ config.hibernateEventListeners.is(hel)
+ }
+
+ def "getServiceRegistry returns null before buildSessionFactory is called"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+
+ expect:
+ config.getServiceRegistry() == null
+ }
+
+ def "addAnnotatedClass adds a class to additionalClasses"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+
+ when:
+ config.addAnnotatedClass(String)
+
+ then:
+ noExceptionThrown()
+ }
+
+ def "addAnnotatedClasses adds multiple classes in batch"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+
+ when:
+ config.addAnnotatedClasses(String, Integer)
+
+ then:
+ noExceptionThrown()
+ }
+
+ def "addPackages adds multiple packages in batch"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+
+ when:
+ def result = config.addPackages("java.lang", "java.util")
+
+ then:
+ result.is(config)
+ }
+
+ def "setApplicationContext with null uses PathMatchingResourcePatternResolver"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+
+ when:
+ config.setApplicationContext(null)
+
+ then:
+ noExceptionThrown()
+ }
+
+ def "setApplicationContext without datasource bean sets session context properties"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+ ApplicationContext appCtx = Stub(ApplicationContext) {
+ containsBean("dataSource") >> false
+ getClassLoader() >> null
+ }
+
+ when:
+ config.setApplicationContext(appCtx)
+
+ then:
+ config.getProperties().containsKey("hibernate.current_session_context_class")
+ config.getProperties().containsKey("hibernate.bytecode.allow_enhancement_as_proxy")
+ config.getProperties().containsKey("hibernate.bytecode.enhancement_metadata_cache")
+ config.getProperties().containsKey("hibernate.enhancer.enableLazyInitialization")
+ config.getProperties().containsKey("hibernate.enhancer.enableDirtyTracking")
+ config.getProperties().containsKey("hibernate.enhancer.enableAssociationManagement")
+ !config.getProperties().containsKey(JdbcSettings.JAKARTA_NON_JTA_DATASOURCE)
+ }
+
+ def "setApplicationContext with datasource bean injects the datasource into properties"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+ DataSource ds = Stub(DataSource)
+ ApplicationContext appCtx = Stub(ApplicationContext) {
+ containsBean("dataSource") >> true
+ getBean("dataSource") >> ds
+ getClassLoader() >> null
+ }
+
+ when:
+ config.setApplicationContext(appCtx)
+
+ then:
+ config.getProperties().get(JdbcSettings.JAKARTA_NON_JTA_DATASOURCE).is(ds)
+ }
+
+ def "setApplicationContext with classLoader sets classloaders property"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+ ClassLoader cl = new URLClassLoader([] as URL[], Thread.currentThread().contextClassLoader)
+ ApplicationContext appCtx = Stub(ApplicationContext) {
+ containsBean("dataSource") >> false
+ getClassLoader() >> cl
+ }
+
+ when:
+ config.setApplicationContext(appCtx)
+
+ then:
+ config.getProperties().get(AvailableSettings.CLASSLOADERS).is(cl)
+ }
+
+ def "setApplicationContext when datasource property already set does not overwrite it"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+ DataSource existingDs = Stub(DataSource)
+ config.getProperties().put(JdbcSettings.JAKARTA_NON_JTA_DATASOURCE, existingDs)
+ DataSource anotherDs = Stub(DataSource)
+ ApplicationContext appCtx = Stub(ApplicationContext) {
+ containsBean("dataSource") >> true
+ getBean("dataSource") >> anotherDs
+ getClassLoader() >> null
+ }
+
+ when:
+ config.setApplicationContext(appCtx)
+
+ then:
+ config.getProperties().get(JdbcSettings.JAKARTA_NON_JTA_DATASOURCE).is(existingDs)
+ }
+
+ def "setApplicationContext with non-default dataSourceName uses correct bean name"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+ config.setDataSourceName("secondary")
+ DataSource ds = Stub(DataSource)
+ ApplicationContext appCtx = Stub(ApplicationContext) {
+ containsBean("dataSource_secondary") >> true
+ getBean("dataSource_secondary") >> ds
+ getClassLoader() >> null
+ }
+
+ when:
+ config.setApplicationContext(appCtx)
+
+ then:
+ config.getProperties().get(JdbcSettings.JAKARTA_NON_JTA_DATASOURCE).is(ds)
+ }
+
+ def "setDataSourceConnectionSource sets dataSourceName, DataSource, and classLoader"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+ DataSource ds = Stub(DataSource)
+ ConnectionSource<DataSource, DataSourceSettings> connSrc = Stub(ConnectionSource) {
+ getName() >> "secondary"
+ getSource() >> ds
+ }
+
+ when:
+ config.setDataSourceConnectionSource(connSrc)
+
+ then:
+ config.dataSourceName == "secondary"
+ config.getProperties().get(JdbcSettings.JAKARTA_NON_JTA_DATASOURCE).is(ds)
+ config.getProperties().containsKey("hibernate.current_session_context_class")
+ config.getProperties().containsKey(AvailableSettings.CLASSLOADERS)
+ }
+
+ def "createBootstrapServiceRegistryBuilder returns a non-null builder"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+
+ when:
+ def builder = config.createBootstrapServiceRegistryBuilder()
+
+ then:
+ builder instanceof BootstrapServiceRegistryBuilder
+ }
+
+ def "createStandardServiceRegistryBuilder returns a non-null builder"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+ BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build()
+
+ when:
+ def builder = config.createStandardServiceRegistryBuilder(bsr)
+
+ then:
+ builder instanceof StandardServiceRegistryBuilder
+
+ cleanup:
+ bsr.close()
+ }
+
+ def "matchesFilter returns false for a non-annotated class"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+ def resolver = new PathMatchingResourcePatternResolver()
+ def readerFactory = new CachingMetadataReaderFactory(resolver)
+ def resources = resolver.getResources("classpath:org/grails/orm/hibernate/cfg/NamingStrategyProvider.class")
+
+ when:
+ boolean matched = false
+ for (def resource : resources) {
+ if (resource.readable) {
+ def reader = readerFactory.getMetadataReader(resource)
+ matched = config.matchesFilter(reader, readerFactory)
+ break
+ }
+ }
+
+ then:
+ !matched
+ }
+
+ def "matchesFilter returns true for an @jakarta.persistence.Entity annotated class"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+ def resolver = new PathMatchingResourcePatternResolver()
+ def readerFactory = new CachingMetadataReaderFactory(resolver)
+ def resources = resolver.getResources("classpath*:org/grails/orm/hibernate/cfg/CfgJpaTestEntity.class")
+
+ when:
+ boolean matched = false
+ for (def resource : resources) {
+ if (resource.readable) {
+ def reader = readerFactory.getMetadataReader(resource)
+ matched = config.matchesFilter(reader, readerFactory)
+ break
+ }
+ }
+
+ then:
+ matched
+ }
+
+ def "scanPackages on a package with no annotated classes throws no exception"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+
+ when:
+ config.scanPackages("java.io")
+
+ then:
+ noExceptionThrown()
+ }
+
+ def "scanPackages discovers @Entity annotated domain classes and calls addAnnotatedClasses"() {
+ given:
+ def config = new HibernateMappingContextConfiguration()
+
+ when:
+ config.scanPackages("org.grails.orm.hibernate.cfg")
+
+ then:
+ noExceptionThrown()
+ }
+}
+
+class HibernateMappingContextConfigurationIntegrationSpec extends HibernateGormDatastoreSpec {
+
+ def setupSpec() {
+ manager.addAllDomainClasses([HmccTestBook, HmccTestAuthor])
+ }
+
+ def "buildSessionFactory produces a working session factory via HibernateDatastore"() {
+ expect:
+ sessionFactory != null
+ !sessionFactory.isClosed()
+ }
+
+ def "getServiceRegistry is non-null after the session factory is built"() {
+ expect:
+ datastore.sessionFactory != null
+ }
+
+ def "HibernateDatastore mappingContext is a HibernateMappingContext with registered entities"() {
+ when:
+ def ctx = mappingContext
+
+ then:
+ ctx instanceof HibernateMappingContext
+ ctx.getPersistentEntity(HmccTestBook.name) != null
+ ctx.getPersistentEntity(HmccTestAuthor.name) != null
+ }
+
+ def "HibernateMappingContextConfiguration addAnnotatedClasses is used by buildSessionFactory"() {
+ when:
+ def entities = mappingContext.persistentEntities
+
+ then:
+ !entities.isEmpty()
+ }
+}
+
+@Entity
+class HmccTestBook implements HibernateEntity<HmccTestBook> {
+ String title
+ HmccTestAuthor author
+ static belongsTo = [author: HmccTestAuthor]
+}
+
+@Entity
+class HmccTestAuthor implements HibernateEntity<HmccTestAuthor> {
+ String name
+ static hasMany = [books: HmccTestBook]
+}
+
+@jakarta.persistence.Entity
+class CfgJpaTestEntity {
+ @jakarta.persistence.Id
+ Long id
+ String name
}
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/MutationQueryDelegateSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/MutationQueryDelegateSpec.groovy
new file mode 100644
index 0000000000..c82df13cee
--- /dev/null
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/MutationQueryDelegateSpec.groovy
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.grails.orm.hibernate.query
+
+import grails.gorm.specs.HibernateGormDatastoreSpec
+import grails.persistence.Entity
+import org.hibernate.query.MutationQuery
+import org.hibernate.query.QueryFlushMode
+
+class MutationQueryDelegateSpec extends HibernateGormDatastoreSpec {
+
+ void setupSpec() {
+ manager.addAllDomainClasses([MutationQueryDelegateTestBook])
+ }
+
+ void setup() {
+ MutationQueryDelegateTestBook.withTransaction {
+ new MutationQueryDelegateTestBook(title: "Book One", pages: 100).save(flush: true, failOnError: true)
+ new MutationQueryDelegateTestBook(title: "Book Two", pages: 200).save(flush: true, failOnError: true)
+ new MutationQueryDelegateTestBook(title: "Book Three", pages: 300).save(flush: true, failOnError: true)
+ }
+ }
+
+ void cleanup() {
+ MutationQueryDelegateTestBook.withTransaction {
+ MutationQueryDelegateTestBook.executeUpdate("DELETE FROM MutationQueryDelegateTestBook")
+ }
+ }
+
+ private MutationQuery buildMutationQuery(String hql) {
+ sessionFactory.currentSession.createMutationQuery(hql)
+ }
+
+ void "constructor wraps the MutationQuery"() {
+ given:
+ MutationQueryDelegateTestBook.withTransaction {
+ MutationQuery mq = buildMutationQuery(
+ "UPDATE MutationQueryDelegateTestBook SET title = :title WHERE title = :old"
+ )
+ MutationQueryDelegate delegate = new MutationQueryDelegate(mq)
+
+ expect:
+ delegate != null
+ }
+ }
+
+ void "setTimeout delegates to the underlying MutationQuery"() {
+ when:
+ MutationQueryDelegateTestBook.withTransaction {
+ MutationQuery mq = buildMutationQuery(
+ "UPDATE MutationQueryDelegateTestBook SET pages = 0 WHERE pages > 0"
+ )
+ MutationQueryDelegate delegate = new MutationQueryDelegate(mq)
+ delegate.setTimeout(30)
+ }
+
+ then:
+ noExceptionThrown()
+ }
+
+ void "setQueryFlushMode delegates to the underlying MutationQuery"() {
+ when:
+ MutationQueryDelegateTestBook.withTransaction {
+ MutationQuery mq = buildMutationQuery(
+ "UPDATE MutationQueryDelegateTestBook SET pages = 0 WHERE pages > 0"
+ )
+ MutationQueryDelegate delegate = new MutationQueryDelegate(mq)
+ delegate.setQueryFlushMode(QueryFlushMode.MANUAL)
+ }
+
+ then:
+ noExceptionThrown()
+ }
+
+ void "setParameter by name delegates and executeUpdate returns affected count"() {
+ when:
+ int count = MutationQueryDelegateTestBook.withTransaction {
+ MutationQuery mq = buildMutationQuery(
+ "UPDATE MutationQueryDelegateTestBook SET pages = :newPages WHERE title = :title"
+ )
+ MutationQueryDelegate delegate = new MutationQueryDelegate(mq)
+ delegate.setParameter("newPages", 999)
+ delegate.setParameter("title", "Book One")
+ delegate.executeUpdate()
+ } as int
+
+ then:
+ count == 1
+ }
+
+ void "setParameter by name with type delegates to MutationQuery"() {
+ when:
+ int count = MutationQueryDelegateTestBook.withTransaction {
+ MutationQuery mq = buildMutationQuery(
+ "UPDATE MutationQueryDelegateTestBook SET pages = :newPages WHERE title = :title"
+ )
+ MutationQueryDelegate delegate = new MutationQueryDelegate(mq)
+ delegate.setParameter("newPages", Integer.valueOf(42), Integer.class)
+ delegate.setParameter("title", "Book Two", String.class)
+ delegate.executeUpdate()
+ } as int
+
+ then:
+ count == 1
+ }
+
+ void "setParameter by position delegates to MutationQuery"() {
+ when:
+ int count = MutationQueryDelegateTestBook.withTransaction {
+ MutationQuery mq = buildMutationQuery(
+ "UPDATE MutationQueryDelegateTestBook SET pages = ?1 WHERE title = ?2"
+ )
+ MutationQueryDelegate delegate = new MutationQueryDelegate(mq)
+ delegate.setParameter(1, 77)
+ delegate.setParameter(2, "Book Three")
+ delegate.executeUpdate()
+ } as int
+
+ then:
+ count == 1
+ }
+
+ void "setParameter by position with type delegates to MutationQuery"() {
+ when:
+ int count = MutationQueryDelegateTestBook.withTransaction {
+ MutationQuery mq = buildMutationQuery(
+ "UPDATE MutationQueryDelegateTestBook SET pages = ?1 WHERE title = ?2"
+ )
+ MutationQueryDelegate delegate = new MutationQueryDelegate(mq)
+ delegate.setParameter(1, Integer.valueOf(88), Integer.class)
+ delegate.setParameter(2, "Book One", String.class)
+ delegate.executeUpdate()
+ } as int
+
+ then:
+ count == 1
+ }
+
+ void "setParameterList with Collection delegates as parameter value"() {
+ when:
+ int count = MutationQueryDelegateTestBook.withTransaction {
+ MutationQuery mq = buildMutationQuery(
+ "DELETE FROM MutationQueryDelegateTestBook WHERE title IN (:titles)"
+ )
+ MutationQueryDelegate delegate = new MutationQueryDelegate(mq)
+ delegate.setParameterList("titles", (Collection<?>) ["Book One", "Book Two"])
+ delegate.executeUpdate()
+ } as int
+
+ then:
+ count == 2
+ }
+
+ void "setParameterList with Object array delegates as parameter value"() {
+ when:
+ int count = MutationQueryDelegateTestBook.withTransaction {
+ MutationQuery mq = buildMutationQuery(
+ "DELETE FROM MutationQueryDelegateTestBook WHERE title IN (:titles)"
+ )
+ MutationQueryDelegate delegate = new MutationQueryDelegate(mq)
+ delegate.setParameterList("titles", ["Book Two", "Book Three"] as Object[])
+ delegate.executeUpdate()
+ } as int
+
+ then:
+ count == 2
+ }
+
+ void "list() throws UnsupportedOperationException"() {
+ when:
+ MutationQueryDelegateTestBook.withTransaction {
+ MutationQuery mq = buildMutationQuery(
+ "UPDATE MutationQueryDelegateTestBook SET pages = 0 WHERE pages > 0"
+ )
+ MutationQueryDelegate delegate = new MutationQueryDelegate(mq)
+ delegate.list()
+ }
+
+ then:
+ thrown(UnsupportedOperationException)
+ }
+
+ void "selectQuery() returns null for mutation queries"() {
+ expect:
+ MutationQueryDelegateTestBook.withTransaction {
+ MutationQuery mq = buildMutationQuery(
+ "UPDATE MutationQueryDelegateTestBook SET pages = 0 WHERE pages > 0"
+ )
+ MutationQueryDelegate delegate = new MutationQueryDelegate(mq)
+ delegate.selectQuery() == null
+ }
+ }
+}
+
+@Entity
+class MutationQueryDelegateTestBook {
+ String title
+ Integer pages
+
+ static constraints = {
+ title nullable: false
+ pages nullable: false
+ }
+}