Springのトランザクション管理

📢 この記事は gemini-2.5-flash によって翻訳されました

トランザクション

トランザクションとは、一連の操作の集まりだよ。これらは分割できないひとつの作業単位で、すべての操作が同時に成功するか、同時に失敗するかのどちらかだね。

操作はこんな感じ:

  • トランザクション開始 (一連の操作が始まる前に、トランザクションを始めること):start transaction / begin
  • トランザクションコミット (この一連の操作がすべて成功したら、トランザクションを確定すること):commit
  • トランザクションロールバック (途中で何か異常が起きたら、トランザクションを取り消すこと):rollback

部署を削除した後に、その部署の従業員も続けて削除するケースを考えてみよう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@Service
public class DeptServiceImpl implements DeptService{
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private EmpMapper empMapper;
    
    @Override
    public void delete(Integer id{
        //1.削除部門
        deptMapper.delete(id);
        
        // 假如这里出现错误,只删除了部门,没删除员工
        
        //2.根据部门id,删除部门下的员工信息
        empMapper.deleteByDetId(id);
    }
}         

上のようにすると、部署がない従業員が残っちゃって、データが不整合になるんだ。

Springのトランザクション管理

アノテーションは@Transactionalだよ。Service層のメソッド、クラス、インターフェースに付けるんだ。

役割:このメソッドのトランザクション管理をSpringに任せるんだ。メソッドの実行前にトランザクションが開始されて、成功すればコミット、異常が起きたらロールバックされるよ。

上記のメソッドだとこうなるね。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@Service
public class DeptServiceImpl implements DeptService{
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private EmpMapper empMapper;
    
    @Transactional // Springにトランザクション管理を任せる
    @Override
    public void delete(Integer id{
        //1.削除部門
        deptMapper.delete(id);
        
        //2.根据部门id,删除部门下的员工信息
        empMapper.deleteByDetId(id);
    }
}

あと、トランザクション管理ログも有効にできるよ。

1
2
3
4
# Springトランザクション管理ログ
logging:
  level:
    org.springframework.jdbc.support.JdbcTransactionManager: debug

トランザクション属性 - ロールバック

デフォルトだと、実行時例外 (RuntimeException) が発生した場合にだけロールバックされるんだ。rollbackFor属性を使えば、どんな例外タイプでトランザクションをロールバックさせるかを制御できるよ。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@Service
public class DeptServiceImpl implements DeptService{
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private EmpMapper empMapper;
    
    // すべての例外でロールバック
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(Integer id{
        //1.削除部門
        deptMapper.delete(id);
        
        //2.根据部门id,删除部门下的员工信息
        empMapper.deleteByDetId(id);
    }
}         

トランザクション属性 - 伝播動作

トランザクション伝播動作っていうのは、あるトランザクションメソッドが別のトランザクションメソッドから呼ばれたときに、その呼ばれたメソッドがどうトランザクションを処理すべきか、ってことなんだ。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Transactional
public void a(){
    // code
    userServices.b();
    // code
}

@Transactional
public void b(){
    // code
}

上記でabを呼んでるけど、baのトランザクションに参加すべきか、それとも自分だけで新しいトランザクションを始めるべきか、どうするんだろうね。

それはpropagation属性で制御できるんだ。

属性値説明
REQUIRED (デフォルト値)トランザクションが必要。あれば参加し、なければ新しく作る。
REQUIRES_NEWトランザクションが必要。あろうとなかろうと、常に新しいトランザクションを作る。
SUPPORTSトランザクションをサポート。あれば参加し、なければトランザクションなしの状態で実行する。
NOT_SUPPORTSトランザクションをサポートしない。トランザクションがあれば一時停止し、トランザクションなしの状態で実行する。
MANDATORYトランザクションが必須。なければ例外をスローする。
NEVERトランザクションがないことが必須。あれば例外をスローする。

使用例を見てみよう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Transactional
public void a(){
    // code
    userServices.b();
    // code
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void b(){
    // code
}

Visits Since 2025-02-28

Hugo で構築されています。 | テーマ StackJimmy によって設計されています。