1

I like to set the Isolationlevel by my self, using the transactionmanager from the Spring Framework combined with myBatis. I was trying a lot of tutorial, but nothing worked.

My application is build as MVC Pattern, that means i have views, models, interfaces used for the dependency-injection from mybatis and a controller class.

I hope someone can give me advice i am new in mybatis and spring. The whole application is running very well but I like to take over controll over the isolationlevels.

This is the spring-configuration.xml file
        <!--<mybatis-spring:scan base-package="de.hrw.model.**"/> -->
    <mybatis-spring:scan base-package="de.hrw.*" />
    <context:component-scan base-package="de.hrw.*" />



     <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/carrental">
        </property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="autoCommit" value="false"></property>
        <property name="registerMbeans" value="true"></property>
        <property name="transactionIsolation"
            value="TRANSACTION_SERIALIZABLE">
        </property> 
    </bean>


    <bean id="sqlSessionFactoryBean"
        class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property> 
        <property name="configLocation" value="classpath:mybatis-config.xml">
        </property>     
    </bean>

    <bean id="carController" class="de.hrw.controller.CarController">
        <property name="transactionManager" ref="transactionManager" /> 
    </bean>

    <bean id="carSearchView" class="de.hrw.view.CarSearchView">
    </bean>


    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>

I am using the dependecy-injection of mybatis to get data from and to the database

example of an iterface package de.hrw.mgmtDAO;

import java.util.List;

import de.hrw.model.CarModel;


public interface ICarMgmt {
    public CarModel selectCarById(final int carId);     
    public List<CarModel> selectAllCars(); 
}

this is the main-class where i include a view (frame)

public class Carrental_main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

          ApplicationContext context = 
                  new ClassPathXmlApplicationContext("spring-config.xml");

          CarController carController = (CarController) context.getBean("carController");

          carController.openSearchView();
          carController.getCarSearchView().setVisible(true);
    }       

}

this is the controller. Here i try to set the isolation level to SERIALIZABLE but it is always set to default (-1)

@Transactional(propagation=Propagation.REQUIRES_NEW , isolation = Isolation.SERIALIZABLE)
public class CarController {
    @Autowired
    private ICarMgmt carMgmt;

private CarSearchView carSearchView;

private ApplicationContext applicationContext;
@Autowired
private PlatformTransactionManager transactionManager;

private TransactionStatus transactionStatus;

private TransactionDefinition defaultTransactionDefinition;

private DataSource dataSource;


public void openSearchView() {
    this.setApplicationContext();
    this.setDefaultTransactionDefinition();
    this.setTransactionStatus();

    this.carSearchView = (CarSearchView) applicationContext
            .getBean("carSearchView");


    try {

        List<CarModel> carList = carMgmt.selectAllCars();


        // this.carSearchView.setResultList(carList);
        this.carSearchView.setLabelList(carList);


        this.carSearchView.createTextFieldList();
        this.carSearchView.createLabelFieldList();


        transactionManager.commit(transactionStatus);

    } catch (DataAccessException e) {
        System.out.println("Error in creating record, rolling back");
        transactionManager.rollback(transactionStatus);
        throw e;
    }
}

 public void setDataSource(DataSource dataSource) {
          this.dataSource = dataSource;

       }

public void setDefaultTransactionDefinition() {
    this.defaultTransactionDefinition = new DefaultTransactionDefinition();
}

public void setApplicationContext() {
    applicationContext = new ClassPathXmlApplicationContext(
            "spring-config.xml");
}

public void setTransactionManager(
        PlatformTransactionManager transactionManager) {
    this.transactionManager = transactionManager;
}

public void setTransactionStatus() {
    this.transactionStatus = transactionManager.getTransaction(defaultTransactionDefinition);

}
Sigurius
  • 41
  • 1
  • 5
  • This looks correct. But are you sure you need SERIALIZABLE? It looks like you need at least InnoDB 5.5 to get support for this - http://stackoverflow.com/questions/6269471/does-mysql-innodb-implement-true-serializable-isolation – AngerClown May 31 '15 at 00:50
  • Serializable is just to Test. I wanna get an Terror if i insert to times the same Object in a row. But it doesen't work. In the beangraph i've seen, that the SessionBeanFactory and the txManager arena't connected. Max be there is the Problem. But i habe no idea how to connect them. – Sigurius May 31 '15 at 07:09
  • What is the spring version you are using? And also mybatis version? – Ian Lim Jun 01 '15 at 02:25
  • MyBatis Version 3.3.0 | MyBatis-Spring 1.2.2 | spring-Context 4.1.6 | InnoDB 5.6 – Sigurius Jun 01 '15 at 07:54

2 Answers2

2

I've finally found a solution. I changed the TransactionDefinition object in the controller to DefaultTransactionDefinition object

private DefaultTransactionDefinition defaultTransactionDefinition;

former it was

private TransactionDefinition defaultTransactionDefinition;

but the TransactionDefinition doesn't provide any setting methods. I was wondering, because in the documentation I found such methods to set the isolationlevel, but this methods are just provided by the DefaultTransactionDefinition. After I've found this failure i added the the following to lines of codes and it finally works

defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
defaultTransactionDefinition.setIsolationLevel(DefaultTransactionDefinition.ISOLATION_REPEATABLE_READ); 

Thx, for all your advises. If someone knows a really good tutorial for MyBatis + Spring and the transaction manager please post a link :D

Sigurius
  • 41
  • 1
  • 5
0

You can apply transaction as shown below in mapper interface(though it is recommended to apply transaction annotation for class, however in mybatis, transaction defined in interface will be applied to proxy class)

import java.util.List;
import de.hrw.model.CarModel;

@Transactional
public interface ICarMgmt {

    @Transactional(isolation = Isolation.SERIALIZABLE)
    public CarModel selectCarById(final int carId);

    public List<CarModel> selectAllCars(); 
}
Karthik Prasad
  • 9,662
  • 10
  • 64
  • 112