How to implement transaction management in Controller layer?

Keywords: Hibernate Spring xml JDBC

stay spring aop transaction management We found that we implemented transaction management in service layer.
Now there are the following scenarios. Let's discuss how to achieve them.
Controller A, Controller B, Controller C... Depending on ServiceA and ServiceB, the save d operation of the above-mentioned Controller needs to synchronize the data between ServiceA and ServiceB.
Because each Controller saves the extraData field of Service B assembled by Json, each Controller is unique. If transaction management is implemented in the Service layer, Service A will become extremely large. It is necessary to determine which Controller comes from the data, and then assemble the extraData field of Service B.
Another way of thinking is, can we put each Controller's extraData field process of assembling Service B in its own Controller and then implement transaction management in Controller?
After testing, add transaction in Controller layer, add declarative transaction interception to Controller in aop:config of spring.xml, and the result is not valid. Adding @Transactional to Controller's class also does not work. Finally, the programmable transaction is implemented.
We configure session Factory and transactionManager in Spring.xml, which can be ignored if declarative transactions have been configured.

<bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="c3p0DataSource" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">#{ nplat['db.dialect'] }</prop>
                <prop key="hibernate.hbm2ddl.auto">none</prop>
                <prop key="hibernate.connection.release_mode">after_transaction</prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.format_sql">false</prop>
                <prop key="hibernate.max_fetch_depth">3</prop><!-- Cascade Depth of Grab -->
                <prop key="hibernate.jdbc.fetch_size">50</prop><!-- Quantity of batch grabbing.mysql I won't support it -->
                <prop key="hibernate.jdbc.batch_size">30</prop><!-- Number of batch writes -->
                <prop key="javax.persistence.validation.mode">none</prop><!-- HiberV3.5 Above need to configure this item -->
                <!-- <prop key="hibernate.cache.use_second_level_cache">true</prop> <prop 
                    key="hibernate.cache.use_query_cache">false</prop> <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop> 
                    force Hibernate Storing data in a secondary cache in a more user-friendly format <prop key="hibernate.cache.use_structured_entries">true</prop> -->
            </props>
        </property>
        <property name="packagesToScan">
            <list>
                <value>com.gina.gc</value>
            </list>
        </property>
    </bean>

    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref bean="sessionFactory" />
        </property>
    </bean>

Then inject transactionManager into each Controller:

@Resource
private PlatformTransactionManager transactionManager;

Here's how to add programmatic transactions to Controller's save method:

@RequestMapping("/save")
@ResponseBody
public String save(@Validated BaseSetting info) {
    DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
    defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
    TransactionStatus status = transactionManager.getTransaction(defaultTransactionDefinition);

    try {
        serviceA.save(A);
        serviceB.save(B);
        ...

        transactionManager.commit(status);
    } catch (Exception e) {
        transactionManager.rollback(status);
        e.printStackTrace();
        log.error("sava *** error" + e.toString());
        return ERROR(e.toString());
    }
    return OK();
}

In this way, transaction management is added to the Controller layer.
Although it is suggested that the transaction be added to Service, different situations and different treatment schemes should be considered comprehensively and applied flexibly in the real project.

Posted by BuzzLY on Wed, 10 Apr 2019 15:48:31 -0700