user2241925
user2241925

Reputation: 351

spring transaction isolation SERIALIZABLE does not work

Code for Main.java:

public class Main {
    public static void main(String[] args) {
        final ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");

        final UserManager userManager = (UserManager) ctx.getBean("userManagerImpl");

        new Thread() {
            public void run() {
                User user = new User();
                user.setUsername("hari18");
                user.setName("haris1");

                userManager.insertUser(user);

                System.out.println("User inserted!");
            }
        } .start();

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread() {
            public void run() {
                List<User> users = userManager.getUsers();
                System.out.println("\nUser list fetched!" + "\nUser count: " + users.size());
                for (User user1 : users) {
                    System.out.println(user1.getUsername());
                }
            }
        } .start();
    }
}    

Code for UserManagerImpl.java:

@Service
@Scope("prototype")
public class UserManagerImpl implements UserManager {
    @Autowired
    private UserDAO userDAO;

    @Override
    @Transactional( propagation=Propagation.REQUIRED , isolation=Isolation.SERIALIZABLE)
    public void insertUser(User user) {
        userDAO.insertUser(user);
    }

    @Override
    @Transactional( propagation=Propagation.REQUIRED , isolation=Isolation.SERIALIZABLE)
    public List<User> getUsers() {
        return userDAO.getUsers();
    }
}

Code for UserDAOImpl.java:

@Service
public class UserDAOImpl extends JdbcDaoSupport implements UserDAO {
    @Autowired
    public UserDAOImpl(DataSource dataSource) {
        setDataSource(dataSource);
    }

    @Override
    public void insertUser(User user) {
        getJdbcTemplate().update("INSERT INTO USER (USERNAME, NAME) VALUES (?, ?)",
            new Object[] {
                user.getUsername(),
                user.getName()
            }
        );

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public List<User> getUsers() {
        List<User> users = getJdbcTemplate().query("SELECT * FROM USER",new UserMapper());
        return users;
    }
}    

Code for spring.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd 
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd">

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

    <context:component-scan base-package="com.byteslounge.spring" />
    <!-- context:component-scan base-package="com.byteslounge.spring" /-->

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/test" />
        <property name="username" value="root" />
        <property name="password" value="password" />
    </bean>

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

</beans>

When run the above main class, theoretically thread one will start first and it has to lock the table USER (because isolation = Isolation.SERIALIZABLE) and when the thread two running it has to wait till the lock released from table USER without read the table from table, but when I run this code it is reading the table and print without wait for first transaction to finish. Why does not USER table lock work even thought the Isolation is SERIALIZABLE???

Upvotes: 1

Views: 3038

Answers (2)

raju muddana
raju muddana

Reputation: 154

I think The Solution is..

In case of reads the lock will be shared among Multiple Thread (Shred Mode). so the 'select' query is executing properly.If you Try with an update/delete query you will get the scenario what you thinking(The another Thread has to wait until first one complete). try in this way.

Upvotes: 1

user2241925
user2241925

Reputation: 351

I got the answer to this question. here problem was time delay between thread one and tow, here I have given time delay as 100ms but this delay is not enough because before insertUser() get the table lock getUsers() occupy the lock and get the data and process it, so once I changed the time delay as 1000ms this problem was resolved. so insertUser() occupied the lock and getUsers() waited till insertUser() finished and commit the insertion part.

Upvotes: 1

Related Questions