Maison  >  Article  >  Java  >  Analyse d'un exemple de gestion des transactions SpringBoot

Analyse d'un exemple de gestion des transactions SpringBoot

WBOY
WBOYavant
2023-05-13 14:13:20582parcourir

1. Définition de la transaction

Une transaction est une unité d'exécution logique constituée d'une séquence d'opérations de base de données en N étapes. Cette série d'opérations est soit toutes exécutées, soit toutes abandonnées.

2. Caractéristiques des transactions

Caractéristiques des transactions : ACID

  • Atomicité : Les transactions sont le plus petit corps d'exécution indivisible dans l'application

  • Cohérence : Le résultat de l'exécution de la transaction doit faire passer les données d'un état cohérent Transition vers un autre état de cohérence

  • Isolement : l'exécution de chaque transaction n'interfère pas les unes avec les autres, et les opérations internes de toute transaction sont isolées des autres transactions

  • Persistance : une fois qu'une transaction est soumise, que fait-on pour les données Toute modification doit être enregistrée dans un stockage permanent

3. Isolation des transactions

Exceptions de concurrence courantes

  • Premier type de mise à jour perdue, deuxième type de mise à jour perdue

  • Lecture sale, lecture non répétable, lecture fantôme

Niveaux d'isolement communs

  • Lecture non validée : lecture des données non validées

  • Lecture validée : lecture des données soumises

  • Lecture répétable : lecture répétable

  • Sérialisable : sérialisation

Le premier type de perte de mise à jour : le rollback d'une transaction entraîne la perte des données mises à jour par une autre transaction.

Le deuxième type de perte de mise à jour : la soumission d'une certaine transaction entraîne la perte des données mises à jour par une autre transaction.

Lecture sale : une certaine transaction lit les données non validées d'une autre transaction.

Lecture non répétable : les résultats d'une certaine transaction lisant les mêmes données avant et après sont incohérents.

Lecture fantôme : pour une certaine transaction, le nombre de lignes interrogées avant et après la même table est incohérent.

Niveau d'isolementPremier type de mise à jour perdueLecture saleDeuxième type de mise à jour perdueLecture non répétableLecture fantômeLecture non validéeOui Oui OuiOuiOuiLecture engagéeNonNonOuiOuiOuiLecture répétableNonNon NonNonOui Verrou partagé (verrou S) : Après que la transaction A ajoute un verrou partagé à certaines données, les autres transactions ne peuvent ajouter qu'un verrou partagé aux données, mais ne peuvent pas ajouter de verrou exclusifVerrou exclusif (verrou X) : Après que la transaction A ajoute un verrou exclusif à certaines données, les autres transactions ne peuvent pas ajouter de verrous partagés ou de verrous exclusifs à ces données. Verrouillage optimiste (personnalisé) Numéro de version, horodatage, etc. Avant de mettre à jour les données, vérifiez si le numéro de version a changé. Si un changement survient, annulez cette mise à jour, sinon mettez à jour les données (numéro de version +1)
Non

Spring transaction management

Transaction déclarative

  • Déclarez les caractéristiques de transaction d'une méthode via la configuration XML.

  • Déclarez les caractéristiques de transaction d'une méthode via des annotations.

Transactions programmatiques

  • Gérez les transactions via TransactionTemplate et effectuez des opérations de base de données via celui-ci.

  • 5. Exemple

    package com.nowcoder.community.service;
    import com.nowcoder.community.dao.AlphaDao;
    import com.nowcoder.community.dao.DiscussPostMapper;
    import com.nowcoder.community.dao.UserMapper;
    import com.nowcoder.community.entity.DiscussPost;
    import com.nowcoder.community.entity.User;
    import com.nowcoder.community.util.CommunityUtil;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.TransactionDefinition;
    import org.springframework.transaction.TransactionStatus;
    import org.springframework.transaction.annotation.Isolation;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.transaction.support.TransactionCallback;
    import org.springframework.transaction.support.TransactionTemplate;
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    import java.util.Date;
    @Service
    //@Scope("prototype")
    public class AlphaService {
        @Autowired
        private AlphaDao alphaDao;
        @Autowired
        private UserMapper userMapper;
        @Autowired
        private DiscussPostMapper discussPostMapper;
        @Autowired
        private TransactionTemplate transactionTemplate;
        public AlphaService() {
    //        System.out.println("实例化AlphaService");
        }
        @PostConstruct
        public void init() {
    //        System.out.println("初始化AlphaService");
        }
        @PreDestroy
        public void destroy() {
    //        System.out.println("销毁AlphaService");
        }
        public String find() {
            return alphaDao.select();
        }
        // REQUIRED: 支持当前事务(外部事务),如果不存在则创建新事务.
        // REQUIRES_NEW: 创建一个新事务,并且暂停当前事务(外部事务).
        // NESTED: 如果当前存在事务(外部事务),则嵌套在该事务中执行(独立的提交和回滚),否则就会REQUIRED一样.
        @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
        public Object save1() {
            // 新增用户
            User user = new User();
            user.setUsername("alpha");
            user.setSalt(CommunityUtil.generateUUID().substring(0, 5));
            user.setPassword(CommunityUtil.md5("123" + user.getSalt()));
            user.setEmail("alpha@qq.com");
            user.setHeaderUrl("https://cache.yisu.com/upload/information/20220823/112/6198.png");
            user.setCreateTime(new Date());
            userMapper.insertUser(user);
            // 新增帖子
            DiscussPost post = new DiscussPost();
            post.setUserId(user.getId());
            post.setTitle("Hello");
            post.setContent("新人报道!");
            post.setCreateTime(new Date());
            discussPostMapper.insertDiscussPost(post);
            Integer.valueOf("abc");
            return "ok";
        }
        public Object save2() {
            transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
            transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
            return transactionTemplate.execute(new TransactionCallback<Object>() {
                @Override
                public Object doInTransaction(TransactionStatus status) {
                    // 新增用户
                    User user = new User();
                    user.setUsername("beta");
                    user.setSalt(CommunityUtil.generateUUID().substring(0, 5));
                    user.setPassword(CommunityUtil.md5("123" + user.getSalt()));
                    user.setEmail("beta@qq.com");
                    user.setHeaderUrl("https://cache.yisu.com/upload/information/20220823/112/6199.png");
                    user.setCreateTime(new Date());
                    userMapper.insertUser(user);
                    // 新增帖子
                    DiscussPost post = new DiscussPost();
                    post.setUserId(user.getId());
                    post.setTitle("你好");
                    post.setContent("我是新人!");
                    post.setCreateTime(new Date());
                    discussPostMapper.insertDiscussPost(post);
                    Integer.valueOf("abc");
                    return "ok";
                }
            });
        }
    }

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer