All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gorm.tools.transaction.TrxService.groovy Maven / Gradle / Ivy

There is a newer version: 7.3.74
Show newest version
/*
* Copyright 2019 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License")
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*/
package gorm.tools.transaction

import groovy.transform.CompileStatic
import groovy.transform.stc.ClosureParams
import groovy.transform.stc.SimpleType

import org.grails.datastore.gorm.GormEnhancer
import org.grails.datastore.gorm.internal.RuntimeSupport
import org.grails.datastore.mapping.core.Datastore
import org.grails.datastore.mapping.core.Session
import org.grails.datastore.mapping.transactions.CustomizableRollbackTransactionAttribute
import org.grails.datastore.mapping.transactions.TransactionCapableDatastore
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.transaction.PlatformTransactionManager
import org.springframework.transaction.TransactionDefinition

import gorm.tools.repository.RepoLookup
import grails.gorm.transactions.GrailsTransactionTemplate
import yakworks.spring.AppCtx

/**
 * A generic way to wrap transaction with closures. Used in the WithTrx trait.
 *  - Work on same principal as @Transactional annotation.
 *  - Doesn't require a domain to use the closure
 *  - uses CustomizableRollbackTransactionAttribute which rollsback on any error
 *    where the domain.withTransaction uses DefaultTransactionDefinition
 *  - Also used as a central place to get the defualt Datastore
 *
 * @author Joshua Burnett (@basejump)
 * @since 7.x
 */
@CompileStatic
class TrxService {

    PlatformTransactionManager transactionManager
    Datastore targetDatastore

    PlatformTransactionManager getTransactionManager() {
        return this.transactionManager != null ? this.transactionManager : GormEnhancer.findSingleTransactionManager()
    }

    @Autowired(required = false)
    void setTargetDatastore(Datastore... datastores) {
        Datastore defds = RuntimeSupport.findDefaultDatastore(datastores)
        this.targetDatastore = defds
        if (defds != null) {
            this.transactionManager = ((TransactionCapableDatastore) defds).transactionManager
        }
    }

    Datastore getTargetDatastore() {
        return this.targetDatastore != null ? this.targetDatastore : GormEnhancer.findSingleDatastore()
    }

    Datastore getDatastore(Class entityClass) {
        def repo = RepoLookup.findRepo(entityClass)
        return repo != null? repo.datastore : getTargetDatastore()
    }

    /**
     * Executes the given callable within the context of a transaction with the given definition
     *
     * @param callable The callable The callable
     * @return The result of the callable
     */
    public  T withTrx(@ClosureParams(value = SimpleType, options = "org.springframework.transaction.support.DefaultTransactionStatus") Closure callable) {

        def tranDef = new CustomizableRollbackTransactionAttribute()
        withTrx(tranDef, callable)

    }

    /**
     * Executes the closure within the context of a transaction for the given {@link org.springframework.transaction.TransactionDefinition}
     *
     * @param callable The closure to call
     * @return The result of the closure execution
     */
    public  T withTrx(Map transactionProperties,
                         @ClosureParams(value = SimpleType, options = "org.springframework.transaction.support.DefaultTransactionStatus") Closure callable) {

        def tranDef = new CustomizableRollbackTransactionAttribute()
        transactionProperties.each { k, v ->
            try {
                tranDef[k as String] = v
            } catch (MissingPropertyException mpe) {
                throw new IllegalArgumentException("[${k}] is not a valid transaction property.")
            }
        }

        withTrx(tranDef, callable)
    }

    /**
     * Executes the closure within the context of a transaction for the given {@link org.springframework.transaction.TransactionDefinition}
     *
     * @param callable The closure to call
     * @return The result of the closure execution
     */
    public  T withTrx(TransactionDefinition definition,
                         @ClosureParams(value = SimpleType, options = "org.springframework.transaction.support.DefaultTransactionStatus") Closure callable) {

        if (!callable) {
            return
        }

        new GrailsTransactionTemplate(getTransactionManager(), definition).execute(callable)
    }

    public  T withNewTrx(@ClosureParams(value = SimpleType, options = "org.springframework.transaction.support.DefaultTransactionStatus")
                                Closure callable) {
        def tranDef = new CustomizableRollbackTransactionAttribute()
        tranDef.propagationBehavior = TransactionDefinition.PROPAGATION_REQUIRES_NEW
        withTrx(tranDef, callable)
    }

    public  T withReadOnlyTrx(@ClosureParams(value = SimpleType, options = "org.springframework.transaction.support.DefaultTransactionStatus")
                                     Closure callable) {
        def tranDef = new CustomizableRollbackTransactionAttribute()
        tranDef.readOnly = true
        withTrx(tranDef, callable)
    }

    /**
     * Executes the closure within the context of a transaction for the given Datastore
     * Will use the tr
     *
     * @param callable The closure to call
     * @return The result of the closure execution
     */
    public  T withTrx(Datastore datastore,
                         @ClosureParams(value = SimpleType, options = "org.springframework.transaction.support.DefaultTransactionStatus") Closure callable) {
        if (!callable) {
            return
        }
        PlatformTransactionManager trxManager
        //if datastore is set then use its transactionManager, useful in multi datasource situations
        if(datastore && datastore instanceof TransactionCapableDatastore){
            trxManager = datastore.transactionManager
        }
        def tranDef = new CustomizableRollbackTransactionAttribute()
        new GrailsTransactionTemplate(trxManager, tranDef).execute(callable)
    }

    public  T withSession(Closure callable){
        getTargetDatastore().withSession callable
    }

    Session getCurrentSession(){
        getTargetDatastore().currentSession
    }

    void flushAndClear() {
        flush()
        clear()
    }

    /**
     * see the static flush method which is called with the getTargetDatastore()
     */
    void flush() {
        TrxUtils.flush(getTargetDatastore())
    }

    /**
     * see the static clear method which is called with the getTargetDatastore()
     */
    void clear() {
        TrxUtils.clear(getTargetDatastore())
    }

    static TrxService bean(){
        AppCtx.get('trxService', TrxService)
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy