Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ä¸ äºå¡ä¸çæ
1.访é®æéé®é¢
javaç访é®æé主è¦æåç§ï¼private<default<protected<publicã
æææäºäºå¡æ¹æ³ï¼å®ä¹äºé误ç访é®æéï¼å°±ä¼å¯¼è´äºå¡åè½åºé®é¢:
 @Service
public class UserService {
   Â
    @Transactional
    private void add(UserModel userModel) {
         saveData(userModel);
         updateData(userModel);
    }
}
springè¦æ±è¢«ä»£çæ¹æ³å¿ é¡»æ¯
public
ç
å¨
AbstractFallbackTransactionAttributeSource
ç±»ç
computeTransactionAttribute
æ¹æ³ä¸æ个å¤æï¼å¦æç®æ æ¹æ³ä¸æ¯publicï¼å
TransactionAttribute
è¿ånullï¼å³ä¸æ¯æäºå¡ã
=====>protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
    // Don't allow no-public methods as required.
    if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
      return null;
    }
    // The method may be on an interface, but we need attributes from the target class.
    // If the target class is null, the method will be unchanged.
    Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
    // First try is the method in the target class.
    TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
    if (txAttr != null) {
      return txAttr;
    }
    // Second try is the transaction attribute on the target class.
    txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
    if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
      return txAttr;
    }
    if (specificMethod != method) {
      // Fallback is to look at the original method.
      txAttr = findTransactionAttribute(method);
      if (txAttr != null) {
        return txAttr;
      }
      // Last fallback is the class of the original method.
      txAttr = findTransactionAttribute(method.getDeclaringClass());
      if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
        return txAttr;
      }
    }
    return null;
  }
2.æ¹æ³ç¨final修饰:
æ个æ¹æ³ä¸æ³è¢«åç±»éæ°ï¼è¿æ¶å¯ä»¥å°è¯¥æ¹æ³å®ä¹æfinalç,ä½å¦æå°äºå¡æ¹æ³å®ä¹æfinalçäºç©ä¼å¤±æã
@Service
public class UserService {
    @Transactional
    public final void add(UserModel userModel){
        saveData(userModel);
        updateData(userModel);
    }
}
springäºå¡åºå±ä½¿ç¨äºaopï¼ä¹å°±æ¯éè¿jdkå¨æ代çæè cglibï¼å¸®æ们çæäºä»£çç±»ï¼å¨ä»£çç±»ä¸å®ç°çäºå¡åè½ã
ä½å¦ææ个æ¹æ³ç¨final修饰äºï¼é£ä¹å¨å®ç代çç±»ä¸ï¼å°±æ æ³éå该æ¹æ³ï¼èæ·»å äºå¡åè½ã
å¦ææ个æ¹æ³æ¯staticçï¼åæ ·æ æ³éè¿å¨æ代çï¼åæäºå¡æ¹æ³ã
Â
3.æ¹æ³å é¨è°ç¨ï¼
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    @Transactional
    public void add(UserModel userModel) {
        userMapper.insertUser(userModel);
        updateStatus(userModel);
    }
    @Transactional
    public void updateStatus(UserModel userModel) {
        doSameThing();
    }
}
å¨äºå¡æ¹æ³addä¸ï¼ç´æ¥è°ç¨äºå¡æ¹æ³updateStatusãä»åé¢ä»ç»çå 容å¯ä»¥ç¥éï¼updateStatusæ¹æ³æ¥æäºå¡çè½åæ¯å 为spring aopçæ代çäºå¯¹è±¡ï¼ä½æ¯è¿ç§æ¹æ³ç´æ¥è°ç¨äºthis对象çæ¹æ³ï¼æ以updateStatusæ¹æ³ä¸ä¼çæäºå¡ã
解å³åæ³ï¼
1ï¼æ°å ä¸ä¸ªServiceæ¹æ³
è¿ä¸ªæ¹æ³é常ç®åï¼åªéè¦æ°å ä¸ä¸ªServiceæ¹æ³ï¼æ@Transactional注解å å°æ°Serviceæ¹æ³ä¸ï¼æéè¦äºå¡æ§è¡ç代ç 移å°æ°æ¹æ³ä¸
@Servcie
public class ServiceA {
   @Autowired
   prvate ServiceB serviceB;
   public void save(User user) {
         queryData1();
         queryData2();
         serviceB.doSave(user);
   }
 }
 @Servcie
 public class ServiceB {
    @Transactional(rollbackFor=Exception.class)
    public void doSave(User user) {
       addData1();
       updateData2();
    }
 }
2ï¼å¨è¯¥Serviceç±»ä¸æ³¨å ¥èªå·±
Servcie
public class ServiceA {
   @Autowired
   prvate ServiceA serviceA;
   public void save(User user) {
         queryData1();
         queryData2();
         serviceA.doSave(user);
   }
   @Transactional(rollbackFor=Exception.class)
   public void doSave(User user) {
       addData1();
       updateData2();
    }
 }
3ï¼éè¿AopContentç±»
å¨è¯¥Serviceç±»ä¸ä½¿ç¨AopContext.currentProxy()è·å代ç对象
@Servcie
public class ServiceA {
   public void save(User user) {
         queryData1();
         queryData2();
         ((ServiceA)AopContext.currentProxy()).doSave(user);
   }
   @Transactional(rollbackFor=Exception.class)
   public void doSave(User user) {
       addData1();
       updateData2();
    }
 }
4.æªè¢«spring管ç
使ç¨springäºå¡çåææ¯ï¼å¯¹è±¡è¦è¢«spring管çï¼éè¦å建beanå®ä¾ã
éè¿@Controllerã@Serviceã@Componentã@Repositoryç注解ï¼å¯ä»¥èªå¨å®ç°beanå®ä¾ååä¾èµæ³¨å ¥çåè½ã
public class UserService {
    @Transactional
    public void add(UserModel userModel) {
         saveData(userModel);
         updateData(userModel);
    }   Â
}
5.å¤çº¿ç¨è°ç¨
@Slf4j
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleService roleService;
    @Transactional
    public void add(UserModel userModel) throws Exception {
        userMapper.insertUser(userModel);
        new Thread(() -> {
            roleService.doOtherThing();
        }).start();
    }
}
@Service
public class RoleService {
    @Transactional
    public void doOtherThing() {
        System.out.println("ä¿årole表æ°æ®");
    }
}
äºå¡æ¹æ³addä¸ï¼è°ç¨äºäºå¡æ¹æ³doOtherThingï¼ä½æ¯äºå¡æ¹æ³doOtherThingæ¯å¨å¦å¤ä¸ä¸ªçº¿ç¨ä¸è°ç¨çã
è¿æ ·ä¼å¯¼è´ä¸¤ä¸ªæ¹æ³ä¸å¨åä¸ä¸ªçº¿ç¨ä¸ï¼è·åå°çæ°æ®åºè¿æ¥ä¸ä¸æ ·ï¼ä»èæ¯ä¸¤ä¸ªä¸åçäºå¡ãå¦ææ³doOtherThingæ¹æ³ä¸æäºå¼å¸¸ï¼addæ¹æ³ä¹åæ»æ¯ä¸å¯è½çã
springçäºå¡æ¯éè¿æ°æ®åºè¿æ¥æ¥å®ç°çãå½å线ç¨ä¸ä¿åäºä¸ä¸ªmapï¼keyæ¯æ°æ®æºï¼valueæ¯æ°æ®åºè¿æ¥ã
====ãprivate static final ThreadLocal<Map<Object, Object>> resources =
  new NamedThreadLocal<>("Transactional resources");
说æï¼åä¸ä¸ªäºå¡ï¼å ¶å®æ¯æåä¸ä¸ªæ°æ®åºè¿æ¥ï¼åªææ¥æåä¸ä¸ªæ°æ®åºè¿æ¥æè½åæ¶æ交ååæ»ãå¦æå¨ä¸åç线ç¨ï¼æ¿å°çæ°æ®åºè¿æ¥è¯å®æ¯ä¸ä¸æ ·çï¼æ以æ¯ä¸åçäºå¡ã
Â
6.表ä¸æ¯æäºå¡
ï¼mysql5ä¹åï¼é»è®¤çæ°æ®åºå¼ææ¯MYISAMã
å®ç好å¤å°±ä¸ç¨å¤è¯´äºï¼ç´¢å¼æ件åæ°æ®æ件æ¯åå¼åå¨çï¼å¯¹äºæ¥å¤åå°çå表æä½ï¼æ§è½æ¯innodbæ´å¥½ã
å建表çæ¶åï¼åªéè¦æ
ENGINE
åæ°è®¾ç½®æ
MyISAM
å³å¯ï¼
CREATEÂ TABLEÂ `category`Â (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `one_category` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
  `two_category` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
  `three_category` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
  `four_category` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
  PRIMARY KEY (`id`)
)Â ENGINE=MyISAMÂ AUTO_INCREMENT=4Â DEFAULTÂ CHARSET=utf8mb4Â COLLATE=utf8mb4_bin
myisam好ç¨ï¼ä½æ个å¾è´å½çé®é¢æ¯ï¼ ä¸æ¯æäºå¡ï¼ myisamè¿ä¸æ¯æè¡éåå¤é®
ï¼
7.æªå¼å¯äºå¡
ï¼1ï¼ä½¿ç¨çæ¯springboot项ç®ï¼é£ä¹ä½ å¾å¹¸è¿ãå 为springbootéè¿
DataSourceTransactionManagerAutoConfiguration
ç±»ï¼å·²ç»é»é»çå¸®ä½ å¼å¯äºäºå¡ã
ï¼2ï¼ä½¿ç¨çè¿æ¯ä¼ ç»çspring项ç®ï¼åéè¦å¨applicationContext.xmlæ件ä¸ï¼æå¨é ç½®äºå¡ç¸å ³åæ°ãå¦æå¿äºé ç½®ï¼äºå¡è¯å®æ¯ä¸ä¼çæçã<!-- é ç½®äºå¡ç®¡çå¨Â -->Â
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">Â
    <property name="dataSource" ref="dataSource"></property>Â
</bean>Â
<tx:advice id="advice" transaction-manager="transactionManager">Â
    <tx:attributes>Â
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>Â
</tx:advice>Â
<!-- ç¨åç¹æäºå¡åè¿å»Â -->Â
<aop:config>Â
    <aop:pointcut expression="execution(* com.susan.*.*(..))" id="pointcut"/>Â
    <aop:advisor advice-ref="advice" pointcut-ref="pointcut"/>Â
</aop:config>Â
Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â äº äºå¡ä¸åæ»
1.é误çä¼ æç¹æ§
å¨ä½¿ç¨
@Transactional
注解æ¶ï¼æ¯å¯ä»¥æå®
propagation
åæ°çã
该åæ°çä½ç¨æ¯æå®äºå¡çä¼ æç¹æ§ï¼springç®åæ¯æ7ç§ä¼ æç¹æ§ï¼
-
 å¦æå½åä¸ä¸æä¸åå¨äºå¡ï¼é£ä¹å å ¥è¯¥äºå¡ï¼å¦æä¸åå¨äºå¡ï¼å建ä¸ä¸ªäºå¡ï¼è¿æ¯é»è®¤çä¼ æå±æ§å¼ãREQUIRED
-
 å¦æå½åä¸ä¸æåå¨äºå¡ï¼åæ¯æäºå¡å å ¥äºå¡ï¼å¦æä¸åå¨äºå¡ï¼å使ç¨éäºå¡çæ¹å¼æ§è¡ãSUPPORTS
-
 å¦æå½åä¸ä¸æä¸åå¨äºå¡ï¼å¦åæåºå¼å¸¸ãMANDATORY
-
 æ¯æ¬¡é½ä¼æ°å»ºä¸ä¸ªäºå¡ï¼å¹¶ä¸åæ¶å°ä¸ä¸æä¸çäºå¡æèµ·ï¼æ§è¡å½åæ°å»ºäºå¡å®æ以åï¼ä¸ä¸æäºå¡æ¢å¤åæ§è¡ãREQUIRES_NEW
-
 å¦æå½åä¸ä¸æä¸åå¨äºå¡ï¼åæèµ·å½åäºå¡ï¼ç¶åæ°çæ¹æ³å¨æ²¡æäºå¡çç¯å¢ä¸æ§è¡ãNOT_SUPPORTED
-
 å¦æå½åä¸ä¸æä¸åå¨äºå¡ï¼åæåºå¼å¸¸ï¼å¦åå¨æ äºå¡ç¯å¢ä¸æ§è¡ä»£ç ãNEVER
-
 å¦æå½åä¸ä¸æä¸åå¨äºå¡ï¼ååµå¥äºå¡æ§è¡ï¼å¦æä¸åå¨äºå¡ï¼åæ°å»ºäºå¡ãNESTED
æå¨è®¾ç½®propagationåæ°çæ¶åï¼æä¼ æç¹æ§è®¾ç½®éäº
@Service
public class UserService {
    @Transactional(propagation = Propagation.NEVER)
    public void add(UserModel userModel) {
        saveData(userModel);
        updateData(userModel);
    }
}
ç®ååªæè¿ä¸ç§ä¼ æç¹æ§æä¼å建æ°äºå¡ï¼REQUIREDï¼REQUIRES_NEWï¼NESTEDã
2.èªå·±åäºå¼å¸¸
å¼åè å¨ä»£ç ä¸æå¨try...catchäºå¼å¸¸
@Slf4j
@Service
public class UserService {
   Â
    @Transactional
    public void add(UserModel userModel) {
        try {
            saveData(userModel);
            updateData(userModel);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }
}
å¼åè èªå·±æè·äºå¼å¸¸ï¼å没ææå¨æåºï¼æ¢å¥è¯è¯´å°±æ¯æå¼å¸¸åæäºã
å¦ææ³è¦springäºå¡è½å¤æ£å¸¸åæ»ï¼å¿ é¡»æåºå®è½å¤å¤ççå¼å¸¸ãå¦æ没ææå¼å¸¸ï¼åspring认为ç¨åºæ¯æ£å¸¸çã
Â
3.æå¨æäºå«çå¼å¸¸
å¼åè 没ææå¨æè·å¼å¸¸ï¼ä½å¦ææçå¼å¸¸ä¸æ£ç¡®ï¼springäºå¡ä¹ä¸ä¼åæ»ã
@Slf4j
@Service
public class UserService {
   Â
    @Transactional
    public void add(UserModel userModel) throws Exception {
        try {
             saveData(userModel);
             updateData(userModel);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new Exception(e);
        }
    }
}
å¼å人åèªå·±æè·äºå¼å¸¸ï¼åæå¨æåºäºå¼å¸¸ï¼Exceptionï¼äºå¡åæ ·ä¸ä¼åæ»ã
å 为springäºå¡ï¼é»è®¤æ åµä¸åªä¼åæ»
RuntimeException
ï¼è¿è¡æ¶å¼å¸¸ï¼å
Error
ï¼é误ï¼ï¼å¯¹äºæ®éçExceptionï¼éè¿è¡æ¶å¼å¸¸ï¼ï¼å®ä¸ä¼åæ»ã
Â
4.èªå®ä¹äºåæ»å¼å¸¸
å¨ä½¿ç¨@Transactional注解声æäºå¡æ¶ï¼ææ¶æ们æ³èªå®ä¹åæ»çå¼å¸¸ï¼springä¹æ¯æ¯æçãå¯ä»¥éè¿è®¾ç½®
rollbackFor
åæ°ï¼æ¥å®æè¿ä¸ªåè½
@Slf4j
@Service
public class UserService {
   Â
    @Transactional(rollbackFor = BusinessException.class)
    public void add(UserModel userModel) throws Exception {
       saveData(userModel);
       updateData(userModel);
    }
}
å¨æ§è¡ä¸é¢è¿æ®µä»£ç ï¼ä¿ååæ´æ°æ°æ®æ¶ï¼ç¨åºæ¥éäºï¼æäºSqlExceptionãDuplicateKeyExceptionçå¼å¸¸ãèBusinessExceptionæ¯æ们èªå®ä¹çå¼å¸¸ï¼æ¥éçå¼å¸¸ä¸å±äºBusinessExceptionï¼æ以äºå¡ä¹ä¸ä¼åæ»ã
5.åµå¥äºå¡åæ»å¤äº
public class UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleService roleService;
    @Transactional
    public void add(UserModel userModel) throws Exception {
        userMapper.insertUser(userModel);
        roleService.doOtherThing();
    }
}
@Service
public class RoleService {
    @Transactional(propagation = Propagation.NESTED)
    public void doOtherThing() {
        System.out.println("ä¿årole表æ°æ®");
    }
}
使ç¨äºåµå¥çå é¨äºå¡ï¼åæ¬æ¯å¸æè°ç¨roleService.doOtherThingæ¹æ³æ¶ï¼å¦æåºç°äºå¼å¸¸ï¼åªåæ»doOtherThingæ¹æ³éçå 容ï¼ä¸åæ» userMapper.insertUseréçå 容ï¼å³åæ»ä¿åç¹ããä½äºå®æ¯ï¼insertUserä¹åæ»äºã
å 为doOtherThingæ¹æ³åºç°äºå¼å¸¸ï¼æ²¡ææå¨æè·ï¼ä¼ç»§ç»å¾ä¸æï¼å°å¤å±addæ¹æ³ç代çæ¹æ³ä¸æè·äºå¼å¸¸ãæ以ï¼è¿ç§æ åµæ¯ç´æ¥åæ»äºæ´ä¸ªäºå¡ï¼ä¸åªåæ»å个ä¿åç¹ã
解å³åæ³ï¼
@Slf4j
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleService roleService;
    @Transactional
    public void add(UserModel userModel) throws Exception {
        userMapper.insertUser(userModel);
        try {
            roleService.doOtherThing();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }
}
==å°å é¨åµå¥äºå¡æ¾å¨try/catchä¸ï¼å¹¶ä¸ä¸ç»§ç»å¾ä¸æå¼å¸¸ãè¿æ ·å°±è½ä¿è¯ï¼å¦æå é¨åµå¥äºå¡ä¸åºç°å¼å¸¸ï¼åªåæ»å é¨äºå¡ï¼èä¸å½±åå¤é¨äºå¡ã
Â
Â