Transaction

μŠ€ν”„λ§μ—μ„œλŠ” λ‘κ°€μ§€μ˜ νŠΈλžœμž­μ…˜ 방법을 μ‚¬μš©ν•œλ‹€.

μ²«λ²ˆμ§ΈλŠ” 선언에 μ˜ν•œ 선언적 νŠΈλžœμž­μ…˜ 이닀.

λ‘λ²ˆμ§ΈλŠ” ν”„λ‘œκ·Έλž¨μ— μ˜ν•œ νŠΈλžœμž­μ…˜ 이닀.

ν”„λ‘œκ·Έλž¨μ— μ˜ν•œ νŠΈλžœμž­μ…˜μ€ try ~ catch ꡬ문을 μ‚¬μš©ν•˜μ—¬ 컀밋과 둀백을 μ΄μš©ν•˜μ—¬ νŠΈλžœμž­μ…˜μ„ μ²˜λ¦¬ν•œλ‹€.

선언적 νŠΈλžœμž­μ…˜μ€ AOPλ₯Ό μ΄μš©ν•˜λŠ” 방식과 μ–΄λ…Έν…Œμ΄μ…˜μ„ μ΄μš©ν•˜λŠ” 방식이 μžˆλ‹€.

AOP λ₯Ό μ΄μš©ν•œ 선언적 νŠΈλžœμž­μ…˜

context-datasource.xml 의 λ‚΄μš©μ„ μˆ˜μ •







Β 
Β 
Β 

















<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd "> 
  
  … μƒλž΅ …

  <!-- Transaction Manager -->
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
  </bean>

  <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
      <tx:method name="get*" read-only="true" />
        <tx:method name="delete*" />
    </tx:attributes>
  </tx:advice>

  <aop:config>
    <aop:pointcut id="transactionPointcut" expression="execution(* com.syaku.bbs.dao.BbsDao.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut" />
  </aop:config>

  <bean id="bbsDao" class="com.syaku.bbs.dao.BbsDao"/>

</beans>

transactionManager μ—μ„œλŠ” dataSource μ •μ˜λ₯Ό μ°Έμ‘°ν•œλ‹€.

κΈ°μ‘΄ jdbc 둜그λ₯Ό 좜λ ₯ν•˜κΈ° μœ„ν•΄ μƒμ„±ν•œ dataSource λ₯Ό μ°Έμ‘°ν•œλ‹€.
λ§Œμ•½ λ‘œκ·Έκ°€ μ—†λ‹€λ©΄ 연결을 μœ„ν•΄ μƒμ„±ν•œ dataSource λ₯Ό μ°Έμ‘°ν•œλ‹€.

tx λŠ” μŠ€ν”„λ§ νŠΈλžœμ μ…˜μ„ λ‹΄λ‹Ήν•˜λ©° tx λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄ 상단에 λ„€μž„μŠ€νŽ˜μ΄μŠ€λ₯Ό μΆ”κ°€ν•˜μ˜€λ‹€.

<tx:method> 속성

속성λͺ… μ—­ν• 
name νŠΈλžœμž­μ…˜μ΄ 적용될 λ©”μ„œλ“œ 이름을 λͺ…μ‹œν•˜λ©° ν•„μˆ˜ 속성이닀.
get* delete* * 이 μ„€μ • κ°€λŠ₯ν•˜λ‹€.
propagation νŠΈλžœμž­μ…˜μ˜ μ „νŒŒλ™μž‘μ„ μ„€μ •ν•œλ‹€.
기본값은 REQUIRED 이닀.
ν•΄λ‹Ή μ˜΅μ…˜μ€ μ•„λž˜μ—μ„œ μ„€λͺ…
isolation νŠΈλžœμž­μ…˜μ˜ 격리 μˆ˜μ€€μ„ μ„€μ •ν•œλ‹€.
기본값은 DEFAULT 이닀.
ν•΄λ‹Ή μ˜΅μ…˜μ€ μ•„λž˜μ—μ„œ μ„€λͺ…
timeout νŠΈλžœμž­μ…˜μ˜ μ‹œκ°„ μ΄ˆκ³Όκ°’μ„ μ„€μ •ν•œλ‹€.
기본값은 -1 이닀.
read-only 읽기 μ „μš© μ—¬λΆ€λ₯Ό μ„€μ •ν•œλ‹€.
기본값은 false이닀.
rollback-for λ‘€λ°±ν•  μ˜ˆμ™Έλ₯Ό μ„€μ •ν•œλ‹€.
μ—¬λŸ¬κ°œλ₯Ό μž…λ ₯ν•  경우 콀마(,) 둜 κ΅¬λΆ„ν•œλ‹€.
기본값은 RuntimeException 이닀.
no-rollback-for λ‘€λ°±ν•˜μ§€ μ•Šμ„ μ˜ˆμ™Έλ₯Ό μ„€μ •ν•œλ‹€.
μ—¬λŸ¬κ°œλ₯Ό μž…λ ₯ν•  경우 콀마(,) 둜 κ΅¬λΆ„ν•œλ‹€.

propagation - μ „νŒŒ μ˜΅μ…˜ (κΈ°λ³Έκ°’ : REQUIRED)

속성값 μ„€λͺ…
REQUIRED λΆ€λͺ¨ νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œ μ‹€ν–‰ν•˜λ©° λΆ€λͺ¨ νŠΈλžœμž­μ…˜μ΄ 없을 경우 μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜μ„ μƒμ„±ν•œλ‹€.
REQUIRES_NEW λΆ€λͺ¨ νŠΈλžœμž­μ…˜μ„ λ¬΄μ‹œν•˜κ³  무쑰건 μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜μ΄ μƒμ„±λœλ‹€.
SUPPORT λΆ€λͺ¨ νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œ μ‹€ν–‰ν•˜λ©° λΆ€λͺ¨ νŠΈλžœμž­μ…˜μ΄ 없을 경우 nontransactionally 둜 μ‹€ν–‰λœλ‹€.
MANDATORY λΆ€λͺ¨ νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œ μ‹€ν–‰λ˜λ©° λΆ€λͺ¨ νŠΈλžœμž­μ…˜μ΄ 없을 경우 μ˜ˆμ™Έκ°€ λ°œμƒλœλ‹€.
NOT_SUPPORT nontransactionally 둜 μ‹€ν–‰ν•˜λ©° λΆ€λͺ¨ νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œ 싀행될 경우 μΌμ‹œ μ •μ§€λœλ‹€.
NEVER nontransactionally 둜 μ‹€ν–‰λ˜λ©° λΆ€λͺ¨ νŠΈλžœμž­μ…˜μ΄ μ‘΄μž¬ν•œλ‹€λ©΄ μ˜ˆμ™Έκ°€ λ°œν–‰νžŒλ‹€.
NESTED ν•΄λ‹Ή λ©”μ„œλ“œκ°€ λΆ€λͺ¨ νŠΈλžœμž­μ…˜μ—μ„œ 진행될 경우 λ³„κ°œλ‘œ μ»€λ°‹λ˜κ±°λ‚˜ 둀백될 수 μžˆλ‹€.
λž˜ν•‘λœ νŠΈλžœμž­μ…˜μ΄ 없을 경우 REQUIRED 와 λ™μΌν•˜κ²Œ μž‘λ™ν•œλ‹€.

isolation - 격리 μˆ˜μ€€ (κΈ°λ³Έκ°’ : DEFAULT)

속성값 μ„€λͺ…
DEFAULT DB μ—μ„œ μ„€μ •λœ κΈ°λ³Έ 격리 μˆ˜μ€€μ„ λ”°λ₯Έλ‹€.
SERIALIZABLE κ°€μž₯ 높은 κ²©λ¦¬μˆ˜μ€€μ„ 가지며 μ‚¬μš©μ‹œ μ„±λŠ₯μ €ν•˜κ°€ μžˆμ„ 수 μžˆλ‹€.
READ_UNCOMMITTED μ»€λ°‹λ˜μ§€ μ•ŠλŠ” 데이터에 λŒ€ν•΄μ„œ 읽기λ₯Ό ν—ˆμš©ν•œλ‹€.
READ_COMMITTED μ»€λ°‹λœ νŠΈλžœμž­μ…˜μ— λŒ€ν•΄ 읽기λ₯Ό ν—ˆμš©ν•œλ‹€.
REPEATABLE_READ λ™μΌν•œ ν•„λ“œμ— λŒ€ν•œ 닀쀑 μ ‘κ·Όμ‹œ λ™μΌν•œ κ²°κ³Όλ₯Ό μ–»μ„μˆ˜ μžˆλŠ” 것을 보μž₯ν•œλ‹€.

Aspectj Expression

<aop:config> μ—μ„œ νŠΈλžœμž­μ…˜μ— μ μš©ν•  λŒ€μƒμ„ μ„€μ •ν•œλ‹€.

* com.syaku.bbs.dao.BbsDao.*(..) 라고 μž…λ ₯ν•œ 뢀뢄을 Aspectj ν‘œν˜„μ‹μ΄λΌκ³  ν•œλ‹€.

execution(μ ‘κ·Όμ œμ–΄μž λ¦¬ν„΄νƒ€μž… νŒ¨ν‚€μ§€ λ©”μ„œλ“œμ΄λ¦„ (인자))

  • * λͺ¨λ‘λ₯Ό μ˜λ―Έν•¨
  • .. 0개 이상을 μ˜λ―Έν•¨

Annotation 을 μ΄μš©ν•œ 선언적 νŠΈλžœμž­μ…˜

AOP λ₯Ό μ΄μš©ν•œ νŠΈλžœμž­μ…˜λ³΄λ‹€ 더 κ°„κ²°ν•˜κ²Œ 처리 κ°€λŠ₯ν•œ 방식

이전에 AOP λ₯Ό μ΄μš©ν•œ 선언적 νŠΈλžœμž­μ…˜ λ°©μ‹μ˜ 섀정을 λͺ¨λ‘ 제거 ν˜Ήμ€ 주석 μ²˜λ¦¬ν•œλ‹€.

단. bean transactionManager λŠ” 남겨둔닀.

context-datasource.xml μˆ˜μ •


























Β 
Β 
Β 




<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd ">

  <bean id="jdbcProp" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="classpath:jdbc.properties" />
  </bean>

  <bean id="dataSourceSpied" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driver}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
  </bean>

  <bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource">
    <constructor-arg ref="dataSourceSpied" />
    <property name="logFormatter">
      <bean class="net.sf.log4jdbc.tools.Log4JdbcCustomFormatter">
        <property name="loggingType" value="MULTI_LINE" />
        <property name="sqlPrefix" value="SQL:::" />
      </bean>
    </property>
  </bean>

  <!-- Transaction Manager -->
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
  </bean>

  <tx:annotation-driven transaction-manager="transactionManager" />
</beans>
속성 μ–΄λ…Έν…Œμ΄μ…˜ μ‚¬μš©
isolation @Transactional(isolation=Isolation.DEFAULT
noRollbackFor @Transactional(noRollbackFor=NoRoleBackTx.class)
noRollbackForClassName @Transactional(noRollbackForClassName="NoRoleBackTx”)
propagation @Transactional(propagation=Propagation.REQUIRED)
readOnly @Transactional(readOnly = true)
rollbackFor @Transactional(rollbackFor=RoleBackTx.class)
rollbackForClassName @Transactional(rollbackForClassName="RoleBackTx”)
timeout @Transactional(timeout=10)

BBSDao 에 νŠΈλžœμž­μ…˜μ„ μœ„ν•΄ μ–΄λ…Έν…Œμ΄μ…˜μ„ μΆ”κ°€ν•˜μ˜€λ‹€.


























Β 
Β 
Β 
Β 
Β 


package com.syaku.bbs.dao;

import java.util.*;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service(value = "bbsDao")
@Transactional(readOnly=true)
public class BbsDao {
  @Resource=(name = "bbsMapper")
  private BbsMapper bbsMapper;

  public List<BbsVo> getSelect(Map map) {
    return this.bbsMapper.select(map);
  }

  public void insert(BbsVo bbsVo) {
    this.bbsMapper.insert(bbsVo);
  }

  public void update(BbsVo bbsVo) {
    this.bbsMapper.update(bbsVo);
  }

  @Transactional
  public void delete(int idx) {
    this.bbsMapper.delete(idx);
    throw new RuntimeException("κ°•μ œλ‘œ 였λ₯˜λ₯Ό λ°œμƒ μ‹œμΌœλ΄„ !! ");
  }
}

ν…ŒμŠ€νŠΈλ‘œ 글을 μ‚­μ œν•΄λ³΄λ©΄ μ‚­μ œλ˜μ§€ μ•ŠλŠ”λ‹€

μŠ€ν”„λ§ νŠΈλžœμž­μ…˜μ€ @Service 에 μ μš©ν•˜λŠ” 것이 λ°”λžŒμ§ν•˜λ‹€.

ν”„λ‘œκ·Έλž¨μ— μ˜ν•œ νŠΈλžœμž­μ…˜

ν”„λ‘œκ·Έλž¨μ— μ˜ν•œ νŠΈλžœμž­μ…˜μ€ try ~ catch 문을 μ‚¬μš©ν•˜μ—¬ μž‘μ„±ν•œλ‹€.

context-datasource.xml 을 ν•˜κΈ°μ™€ 같이 μˆ˜μ •ν•œλ‹€.

<!-- Transaction Manager -->
<bean id="" class="">
  <property name="dataSource" ref="dataSource">
</bean>












Β 
Β 
Β 
Β 


@Resource(name = "transactionManager")
protected DataSourceTransactionManager txManager;

public void insert(BbsVo bbsVo) {
  DefaultTransactionDefinition def = new DefaultTransactionDefinition();
  def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
  TransactionStatus txStatus = txManager.getTransaction(def);

  try {
    this.bbsMapper.insert(bbsVo);
    int a = 1 / 0;
    txManager.commit(txStatus);
  } catch(Exception e) {
    txManager.rollback(txStatus);
    throw new Exception(e.getMessage());
  }
}

μƒμœ„ @Controller μ†ŒμŠ€

try {
  if (idx == null || idx == 0) {
    this.bbsDao.insert(bbsVo);
    xml.setMessage("μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.");
    xml.setError(false);
  } else {
    this.bbsDao.update(bbsVo);
    xml.setMessage("μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.");
    xml.setError(false);
  }
} catch (Exception e) {
  xml.setMessage(e.getMessage());
  xml.setError(true);
}