Announcement Announcement Module
Collapse
No announcement yet.
Create if doesn't exist Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Create if doesn't exist

    Hello,

    In my application I have spring managed service:

    Code:
       <bean id="myService" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target">
                <bean class="com.xxx.management.service.MyServiceImpl">
                    <property name="userDao"><ref bean="UserDao"/></property>
                </bean>
            </property>
            <property name="proxyInterfaces">
                <value>com.xxx.management.service.MyService</value>
            </property>
            <property name="interceptorNames">
                <list>
                    <value>serviceTransactionInterceptor</value>
                    <value>hibernateInterceptor</value>
                </list>
            </property>
        </bean>
    with following method

    Code:
    public void createTask(String username, String data) {
      ...
      User user = userDao.createOrFind(username);
      ...
    }
    The problem arises when this method is called from web service with same username (which is not yet in the database). First thread enters createOrFind method, performs find with no result and tries to create user. second thread (executed in parallel) also finds no user with this username and tries to create one.

    Code:
       public User createOrFind(String login) {
        	StringBuilder query = new StringBuilder(" where user.login = :login");
        	Map<String, Object> param = new HashMap<String, Object>();
        	param.put("login", login);
        	
        	Collection<EfficeUser> list = find(query.toString(), param);
        	
        	if (list.isEmpty()) {
        		User user = new User();
        		user.setLogin(login);
        		return create(user);
        	} else {
        		return list.iterator().next();
        	}
        }
    How can i avoid this race condition? Is it possible somehow to lock table "user" until createOrFind method ends?

  • #2
    Hello,

    I can think of two options, and I hope at least one of them will work:

    1) Make the method createOrFind synchronized:

    Code:
    public synchronized User createOrFind(String login) {
    ...
    2) The other way is to leave the transaction synchronization to the database. So try putting the @Transactional annotation to the same method:


    Code:
    @Transactional
    public User createOrFind(String login) {
    ...
    Hope this helps!

    Regards,
    Ivan

    Comment

    Working...
    X