简体   繁体   English

Spring 数据中的事务管理 REST

[英]Transaction Management in Spring Data REST

Do we have any in-built transaction management when using Spring Data REST or it has to be manually maintained/handled from the calling application/service.使用 Spring 数据 REST 时,我们是否有任何内置事务管理,或者必须从调用应用程序/服务手动维护/处理。

Say, I have two calls(first POST(for creation) and PATCH(update/insert association resource using uri-lists)) which I want to be considered as a transaction.比如说,我有两个调用(第一个 POST(用于创建)和 PATCH(使用 uri-lists 更新/插入关联资源)),我想将它们视为一个事务。

Thanks Bharath谢谢巴拉特

In spring data rest every repository action runs within a transaction. 在春季数据休息中,每个存储库操作都在事务内运行。 Even the event handlers are not running inside the repository transaction. 甚至事件处理程序也没有在存储库事务中运行。 And of course different actions on the REST API do run in separate transactions. 当然,对REST API的不同操作会在单独的事务中运行。

Here is an interesting question on this topic: Handle spring-data-rest application events within the transaction 这是一个有关此主题的有趣问题: 处理事务中的spring-data-rest应用程序事件

If you want to have creation and association in one transaction then the only way to achieve this with your current entity mapping is to create a custom controller that does just that. 如果要在一个事务中进行创建和关联,则使用当前实体映射实现此目的的唯一方法是创建一个自定义控制器来完成该任务。

An alternative mapping strategy would be to treat the associated entity as a containment - so the associated entity does not have an exported repository and is maintained within the parent. 另一种映射策略是将关联实体视为一个容器-因此关联实体没有导出的存储库,而是在父级中维护。

The who point of REST is to have isolated units of work. REST的重点是拥有独立的工作单元。 If you are wanting to keep transactions open across calls it's probably a sign you need to adjust your RESTful strategy. 如果您希望保持跨呼叫的事务开放,则可能是您需要调整RESTful策略的信号。

Have a look at: Transaction strategy for microservices 看看: 微服务的交易策略

I found this question when researching the transaction behavior of data-rest.我在研究data-rest的事务行为时发现了这个问题。

I needed control over the transaction behavior of the default controllers, especially during serialization of relationships, so i could mark transactions as read-only and route them to read-replicas of our database.我需要控制默认控制器的事务行为,尤其是在关系序列化期间,因此我可以将事务标记为只读并将它们路由到我们数据库的只读副本。

By default every call to a repository has its own transaction and database access during events or resource-assembly is managed by hibernate directly, outside of these transactions.默认情况下,对存储库的每次调用都有自己的事务和数据库访问,事件或资源组装由 hibernate 在这些事务之外直接管理。 There is no intended way for users to control transactions.用户没有预定的方式来控制交易。

Spring does however provide methods to do that using aop-interceptors.然而,Spring 确实提供了使用 aop 拦截器的方法。 These interceptors use a property source do decide weather or not a method requires a transaction.这些拦截器使用属性源来决定天气或方法是否需要事务。 Springs own Transactional-Annotation is nothing more than one of these property-sources. Springs 自己的 Transactional-Annotation 只不过是这些属性来源之一。

The following Configuration creates an advisor for the default rest-controllers that creates customized transactions for some Methods:以下配置为默认的 rest-controllers 创建一个顾问程序,为一些方法创建自定义事务:


@Configuration
@ConditionalOnClass(name = {
    "org.springframework.data.rest.webmvc.RepositoryEntityController",
    "org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController",
    "org.springframework.data.rest.webmvc.RepositorySearchController"
})
public class RepositoryRestControllerTransactionConfiguration {

    /**
     * A custom Transaction Advisor that starts customized transactions based on what data-rest controller method is called
     *
     * @param transactionManager
     * @return
     */
    @Bean
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
        TransactionManager transactionManager) {

        //Specify transaction management methods and attribute values required for transaction control
        MethodMapTransactionAttributeSource source = new MethodMapTransactionAttributeSource();
        Map<String, TransactionAttribute> methodMap = new HashMap<>();

        // methods are identified by their FQDN, simple placeholders using * are possible
        // methods that should only require reads
        methodMap.put("org.springframework.data.rest.webmvc.RepositoryEntityController.get*", createTransactionRule(true));
        methodMap.put("org.springframework.data.rest.webmvc.RepositoryEntityController.headForItemResource", createTransactionRule(true));
        methodMap.put("org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.follow*", createTransactionRule(true));
        methodMap.put("org.springframework.data.rest.webmvc.RepositorySearchController.execute*", createTransactionRule(true));

        // methods that will require write
        methodMap.put("org.springframework.data.rest.webmvc.RepositoryEntityController.put*", createTransactionRule(false));
        methodMap.put("org.springframework.data.rest.webmvc.RepositoryEntityController.patch*", createTransactionRule(false));
        methodMap.put("org.springframework.data.rest.webmvc.RepositoryEntityController.delete*", createTransactionRule(false));
        methodMap.put("org.springframework.data.rest.webmvc.RepositoryEntityController.post*", createTransactionRule(false));
        methodMap.put("org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.delete*", createTransactionRule(false));
        methodMap.put("org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.create*", createTransactionRule(false));

        source.setMethodMap(methodMap);
        source.afterPropertiesSet();

        // Generate an AOP Advisor that controls transactions
        // Advice for transaction control (TransactionInteceptor)
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(source);
        advisor.setAdvice(new TransactionInterceptor(transactionManager, source));
        return advisor;
    }

    private RuleBasedTransactionAttribute createTransactionRule(boolean readOnly) {
        RuleBasedTransactionAttribute rule = new RuleBasedTransactionAttribute();

        rule.setReadOnly(readOnly);

        return rule;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM