SpringBoot新特性之@Transactional

Spring的事物注解是@Transactional,加上@Transactional可以将对多个数据库更新操作作为一个数据来提交。例如:

@RestController
@RequestMapping("/register")
public class RegisterController {

    @Autowired
    private ProducerService producerService;

    @RequestMapping("/producer")
    @Transactional(rollbackFor = Exception.class)
    public Long registerProducer(@RequestBody ProducerDTO producerDTO) {
        return producerService.registerProducer(producerDTO);
    }
}

当我们传递一个producerDTO进来后,调用Service服务,Service服务又会调用dao把数据存到数据库。

@Service
public class ProducerServiceImpl implements ProducerService {
    @Autowired
    private ProducerDao producerDao;

    @Override
    public Long registerProducer(ProducerDTO producerDTO) {
        Producer producer = new Producer();
        BeanUtils.copyProperties(producerDTO, producer);
        producerDao.insertSelective(producer);
        return producer.getId();
    }
}
<insert id="insertSelective" parameterType="com.waimaibang.console.model.Producer" useGeneratedKeys="true" keyProperty="id">
    <!--
      WARNING - @mbg.generated
      This element is automatically generated by MyBatis Generator, do not modify.
    -->
    insert into producer
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="name != null">
        name,
      </if>
      <if test="createTime != null">
        create_time,
      </if>
      <if test="updateTime != null">
        update_time,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=BIGINT},
      </if>
      <if test="name != null">
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="createTime != null">
        #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="updateTime != null">
        #{updateTime,jdbcType=TIMESTAMP},
      </if>
    </trim>
  </insert>

这是很多开发人员都习以为常的操作。

但是在SpringBoot 2.0中,如果在单元测试中使用@Transactional会怎么样呢?

@RunWith(SpringRunner.class)
@SpringBootTest
public class ConsoleRegisterTest {

    @Autowired
    private ProducerDao producerDao;
    @Autowired
    private ConsumerDao consumerDao;
    @Autowired
    private DestinationDao destinationDao;

    /**
     * 模拟控制台producer/consumer/destination注册服务
     * @Transactional 不提交修改
     */
    @Test
    @Transactional
    public void loginTest() {
        Long producerId = registerProducer();
        Long consumerId = registerConsumser();
        Long destinationId = registerDestination();
        //绑定producerId、destinationId
        int producerDestinationInsertResult = destinationDao.bindProducerDestination(producerId, destinationId);
        //绑定consumerId、destinationId
        int consumerDestinationInsertResult = destinationDao.bindConsumerDestination(consumerId, destinationId);
        System.out.printf("register a new producer, id = %s%n", producerId);
        System.out.printf("register a new consumer, id = %s%n", consumerId);
        System.out.printf("register a new destination, id = %s%n", destinationId);
        System.out.printf("register a new producerDestination, result = %s%n", producerDestinationInsertResult > 0);
        System.out.printf("register a new consumerDestination, result = %s%n", consumerDestinationInsertResult > 0);

    }

    /**
     * 模拟注册producer
     * @return
     */
    public Long registerProducer() {
        Producer producer = new Producer();
        producer.setName("test_producer");
        producerDao.insertSelective(producer);
        return producer.getId();
    }

    /**
     * 模拟注册consumer
     * @return
     */
    public Long registerConsumser() {
        Consumer consumer = new Consumer();
        consumer.setName("test_producer");
        consumerDao.insertSelective(consumer);
        return consumer.getId();
    }

    /**
     * 模拟注册destination
     * @return
     */
    public Long registerDestination() {
        Destination destination = new Destination();
        destination.setName("test_destination");
        destinationDao.insertSelective(destination);
        return destination.getId();
    }

 }

看下控制台的输出结果:

register a new producer, id = 3
register a new consumer, id = 3
register a new destination, id = 3
register a new producerDestination, result = true
register a new consumerDestination, result = true

但是再观察一下数据库,发现数据库中并未有新的数据插入。






扫描二维码关注公众号,回复: 1453496 查看本文章

可以发现,在单元测试中加入了@Transactional并未导致事物的提交。所以在SpringBoot2.0的单元测试中使用@Transactional对可以对dao进行重复利用而不会担心测试数据污染了数据库。


猜你喜欢

转载自blog.csdn.net/shixuetanlang/article/details/79942909