Spring 4.0.0、Hibernate 4.2.8、および Ms SQL Server 8 を使用してアプリを開発しています。これは、DB テーブルでサポートされ、Hibernate VO (CustomSequence) でマップされたカスタム シーケンスを使用します。
このシーケンスは、サービス コール内でアクセスされます。
- メイン サービスが独自のトランザクションを開始する
- コードを実行し、何かを実行し、クエリを実行します...
シーケンス値のシーケンス サービスを呼び出します (SequenceService)
SequenceService が独自のトランザクションを開始する (REQUIRES_NEW)
SequenceService はオブジェクトを見つけ、値を返し、次の値を保存します
メイン サービスは値を取得し、ビジネス オブジェクトに設定して保存します (この時点で、シーケンス値は内部の新しいトランザクションによって既にコミットされています)。
- 出口
カスタム シーケンスを管理するサービスのスニペット:
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
@Service("sequenceService")
public class SequenceService implements ISequenceService {
@Autowired
private ISequenceDao sequenceDao;
private Integer getSequence() {
CustomSequence sequenceOut = sequenceDao.find();
final Integer nextVal = sequenceOut.getNextVal();
sequenceOut.setNextVal(nextVal + 1);
sequenceDao.save(sequenceOut);
return nextVal;
}
}
私たちの問題は、シリアライズ可能な属性が完全に無視されるため、2 つの同時スレッドが getSequence メソッドにアクセスして同じ値を取得することです。
TransactionSynchronizationManager で分離を確認すると、シリアライズ可能 (値 = 8) の値は正しいようです。
...
Integer isolation = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
...
私たちの春のxmlファイルはこれです:
<context:annotation-config />
<context:component-scan base-package="dev.app"/>
<tx:annotation-driven />
<bean name="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/appDatasource"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" lazy-init="false" >
<property name="dataSource"> <ref bean="dataSource" /></property>
<property name="packagesToScan" value="dev.app.model"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<!-- Disable LOB creation as connection -->
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
</props>
</property>
</bean>
これらのコマンドを使用してMS SQL Management Studioでデータベースのシリアル化可能な機能を確認し、アプリコードを実行しましたが、機能しました(スタジオがコミットするまでコードをブロックしました):
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
UPDATE CUSTOM_SEQUENCE set NEXTVAL = 1000;
WAITFOR DELAY '00:1:00'
COMMIT
何が起こっているかの手がかりはありますか? 私はインターネットで多くの情報を読みましたが、役に立ちませんでした
よろしくお願いします!