2013-10-25 3 views
0

나 최대 절전 모드 4.2.5 사용하고 있는데 봄 3.2.4 JPA, 최대 절전 모드와.동시성 JPA 주석 봄

내가 서비스 내에서 다음과 같은 방법을 fooDao가

@Override 
@Transactional 
public Foo getFoo(String fooName) { 
    Foo foo = fooDao.findByName(fooName); 
    if (foo == null) 
     return null; 
    foo.setBar(new Date()); 
    return fooDao.save(foo); 
} 

단지를 autowire interface FooDao extends JpaRepository<Foo, Long>

지금은 여러 스레드가 getFoo 방법에 액세스하는 경우 다음과 같은 문제가 발생 :

Thread 1: Foo foo1 = getFoo("name1"); 
Thread 2: Foo foo2 = getFoo("name2"); 

하지만, foo1.getName() == foo2.getName() == "name2" (또는 "name1"). 이것은 아마도 저장하고 select last_update_id

내가 트랜잭션 격리를 추가하려고 사이에 전환 스레드 동시성 문제이지만,이 역시 도움이되지 않습니다. 이걸 어떻게 막을 수 있습니까?

편집을 (방법에 synchronized을 분명히 도움이되지 않습니다) : 내 ApplicationContext를 :

<?xml version="1.0" encoding="UTF-8"?> 
<beans ..."> 
    <!-- ======== BoneCP ======== --> 
    <bean id="mainDataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close"> 
     <!-- ... --> 
    </bean> 
    <!-- ======== SPRING ======== --> 
    <context:annotation-config /> 
    <context:component-scan base-package="foo.bar" /> 
    <jpa:repositories base-package="foo.bar" /> 
    <bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy"> 
     <property name="targetDataSource"> 
      <ref local="mainDataSource" /> 
     </property> 
    </bean> 
    <!-- ======== HIBERNATE/JPA ======== --> 
    <bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
     <property name="generateDdl" value="false" /> 
     <property name="showSql" value="false" /> 
     <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" /> 
     <property name="database" value="MYSQL" /> 
    </bean> 
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="packagesToScan" value="de.cmr.cmair.server.db.model" /> 
     <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" /> 
     <property name="persistenceUnitName" value="persistenceUnit" /> 
     <property name="jpaProperties"> 
      <props> 
       <prop key="hibernate.hbm2ddl.auto">validate</prop> 
       <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
       <prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop> 
       <prop key="hibernate.show_sql">false</prop> 
       <prop key="hibernate.format_sql">true</prop> 
       <prop key="hibernate.use_sql_comments">true</prop> 
       <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop> 
       <prop key="hibernate.current_session_context_class">jta</prop> 
      </props> 
     </property> 
    </bean> 
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
     <property name="entityManagerFactory" ref="entityManagerFactory" /> 
    </bean> 
    <tx:annotation-driven transaction-manager="transactionManager" /> 
    <!-- the transactional advice --> 
    <tx:advice id="txAdvice" transaction-manager="transactionManager"> 
     <tx:attributes> 
      <tx:method name="get*" read-only="true" /> 
      <tx:method name="*" propagation="REQUIRED" /> 
     </tx:attributes> 
    </tx:advice> 
    <aop:config> 
     <aop:pointcut id="allDaoMethods" expression="execution(* de.cmr.cmair.server.db.service.*.*(..))" /> 
     <aop:advisor advice-ref="txAdvice" pointcut-ref="allDaoMethods" /> 
    </aop:config> 
</beans> 

푸 클래스 :

@Entity 
@Table(name = "FOO") 
public class Foo { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "ID", unique = true, nullable = false) 
    private long id; 
    @Column(name = "BAR") 
    private Date bar; 
    @Column(name = "NAME", length = 225) 
    private String name; 

    // ... setters/getters 
} 

나는 단지 내가 버전을 사용하지 않는 실현/낙관적 인 잠금,하지만이 문제에 어떤 영향을 미치는지 확실하지 않습니다.

+0

스프링 구성을 포함하십시오. –

+0

왜 이미 존재하는 엔티티를 저장합니까? 너 뭐하려고? –

+0

JPADao의'.save'는 실제로 내가 아는 한 "saveOrUpdate"입니다. 응용 프로그램에서 나는 사용자 로그인 날짜를 저장하려고합니다. 또한 문서에서 "저장 작업으로 엔티티 인스턴스가 완전히 변경되었을 수 있으므로 반환 된 인스턴스를 추가 작업에 사용하십시오." 스프링 구성을 추가했습니다. – incaseoftrouble

답변

0

가장 좋은 해결책은 낙관적 잠금을 가지고 있거나 레코드는 사용자가 레코드를 편집 할 때 고정해야합니다.

+0

낙관적 인 잠금 장치가 도움이 되니? 낙관적 인 잠금 기능을 사용하면 동일한 객체에 대해 병렬 편집을 방지하는 데 도움이됩니다. – incaseoftrouble

+0

낙관적 잠금은 다른 사용자가 업데이트 한 커밋 레코드를 방지합니다. – Arvind