SpringMVC事務ロールバック機構


Spring事物では、Springによってデータベースのデータ接続を管理しています.@Transactionはpublic方法に適用するだけで有効です.コメントを取得する時、AbstractFallbackTransation SourceのcomputterTransation Attribute方法を呼び出します.
private TransactionAttribute computeTransactionAttribute(Method method, Class> targetClass) {
		// Don't allow no-public methods as required.
        //   public      
		if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
			return null;
		}
    //       
}
この方法は、ターゲットメソッドの修飾子がpublicであるかどうかを確認します.publicでないと、@Transationの属性情報を取得できません.最終的にはTransaction Intercepterにこの目標方法をブロックさせて事務管理をさせない.
Springがthrow new RuntimeExceptionに捕獲された時、物事が戻ってきます.

	@Transactional
	public void insertRole(RoleBean roleBean) {
		roleDao.insertRole(roleBean);
		throw new RuntimeException();
	}
Springがthrow new Exceptionに捕獲された場合、物事は戻りません.(下記のコードはコンパイルできません.説明だけです.)

	@Transactional
	public void insertRole(RoleBean roleBean) {
		roleDao.insertRole(roleBean);
		throw new Exception();
	}
この時Exceptionの異常を捕獲するには、注釈@Transactiol(rollbackFor=Exception.class)が必要です.複数であれば、rollbackFor={Exception.class、Exceptions.class}ができます.

	@Transactional(rollbackFor=Exception.class)
	public void insertRole(RoleBean roleBean) {
		roleDao.insertRole(roleBean);
		throw new Exception();
	}
  Spring aop  異常捕獲原理:ブロックされた方法は明示的に異常を投げなければならず、自分でtry catchを行うことができません.このようにaopエージェントは方法の異常を捕まえて、ロールバックを行うことができます.デフォルトではaopはthrow new RuntimeExceptionの異常だけを捕獲します.
物事の方法にtry catchを入れると、Springが異常を捕まえられなくなり、データを転がすことができなくなります.データは正常に保存されていて、ロールバックできません.

	@Transactional
	public void insertRole(RoleBean roleBean) {
		try {
			roleDao.insertRole(roleBean);
			throw new RuntimeException();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
したがって、cathcの後に方法を加えれば、二つのdelete方法に物事を加えなくても、成功することができます.(Spring事物はデフォルトでは、方法運行時に、一つのものがあったら、このものに加入して、さもなくば新しいものを作成します.insertRoleは事務をプラスしたので、その内にroleDao.insertRole()小包されることがあります.最後の2行のdeleteRoleId 1とdeleteRoleId 2も同じ事務管理の下で、deleteRoleId 1は事務管理をすると表示されますが、伝播レベルは特に明記されていませんので、デフォルトの事務伝播行為(propagation=Propgation.REQUID)したがって、deleteRoleId 1は、トランザクションの注釈がある場合、外部の方法insertRoleは、新しい事務を自分で建てます.しかし、insertRoleはすでに事務があります.ですから、deleteRoleId 1はinsertRoleの事務に参加します.自分のものを使うことはありません.)

	@Transactional
	public void insertRole(RoleBean roleBean) {
		try {
			roleDao.insertRole(roleBean);
			throw new RuntimeException();
		} catch (Exception e) {
			e.printStackTrace();
		}
		deleteRoleId1(roleId);
		deleteRoleId2(roleId);
	}

	@Transactional
	public void deleteRoleId1(Integer roleId) {
		roleDao.deleteRoleId(roleId);
	}

	public void deleteRoleId2(Integer roleId) {
		roleDao.deleteRoleId(roleId);
	}
だからSpringで物事を戻したいなら、自分で物事を捕獲したり、捕獲したりしないでください.catchの中で一つの間違いを投げたら、Springは物事が逆戻りします.

	@Transactional
	public void insertRole(RoleBean roleBean) {
		try {
			roleDao.insertRole(roleBean);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException();
		}
	}
	
	@Transactional
	public void insertRole(RoleBean roleBean) {
		if (roleBean != null) {
			roleDao.insertRole(roleBean);
		}else{
			throw new RuntimeException();
		}
	}
insertRoleに事務がない場合、DeleteRoleIdを呼び出し、DeleteRoleId方法に異常がない場合でも、Spring事務はデータをロールバックすることができません.Spring事務はAOPダイナミックエージェントですので、自分で自分の方法を呼び出して、代理対象を生成しません.AOPがありません.これはSpring事務の自動呼び出しが無効になったということです.(insertRole方法に@Transactional事務の注釈を加えると、データはロールバックし、前の文の事務の伝播を参照する)


	public void insertRole(RoleBean roleBean) {
		deleteTerminalByRoleId(3);
	}

	@Transactional
	public void deleteRoleId(int roleId) {
		roleDao.deleteRoleId(roleId);
		throw new RuntimeException();
	}
 
以上が現在理解されているSpringのロールバックメカニズムです.問題があればお互いに勉強することができます.