<small id='cdMsqDWl'></small> <noframes id='jn957dS'>

  • <tfoot id='w1GdjCBEmR'></tfoot>

      <legend id='OuHJ'><style id='4pXZQlGf'><dir id='Gc1BxKAL'><q id='kTh34X'></q></dir></style></legend>
      <i id='hXbE1'><tr id='x4Mzr'><dt id='Tvw0FP2MY'><q id='4XFA5fUdM'><span id='ZhfUuDx'><b id='udZSRB'><form id='9vUxyg'><ins id='ymEQo'></ins><ul id='9koE'></ul><sub id='kgiCbJ'></sub></form><legend id='VIy4p0'></legend><bdo id='3uow2SICM'><pre id='A2swMhF'><center id='DETw'></center></pre></bdo></b><th id='HGFc'></th></span></q></dt></tr></i><div id='zJkSa7E'><tfoot id='3pukTm'></tfoot><dl id='o0fk6M'><fieldset id='PYOixs9aBt'></fieldset></dl></div>

          <bdo id='8xOuh9Eor'></bdo><ul id='QwThrF'></ul>

          1. <li id='JGmoZry'></li>
            登陆

            Spring业务传达特点有那么难吗?看这一篇就够了

            admin 2019-12-12 178人围观 ,发现0个评论

            小编文笔功力尚浅,如有不当,请大方指出,必定感激不尽

            学习东西要知行合一,假如仅仅知道理论而没实践过,那么把握的也不会特别厚实,估量过几天就会忘掉,接下来咱们一同实践来学习Spring业务的传达特点。

            传达特点

            传达特点界说的是当一个业务办法碰到另一个业务办法时的处理行为,一共有七种行为,界说如下

            其实只看概念的话现已很开门见山了阐明晰每个传达性的作用,此刻咱们再用详细的比如演示一下每个传达性特点下的行为。

            此次演示咱们运用的是H2数据库,这个数据库是作用在内存里边的,所以关于咱们演示业务作用来说正好,无需咱们在进行其他的装备了,咱们新建一个表。将下面句子放在schema.sql文件里边即可,SpringBoot程序在发动的时分就会主动为咱们在内存里边树立这样的一个表。

            CREATE TABLE FOO (ID INT IDENTITY, BAR VARCHAR(64));

            演示之前咱们会界说两个类FooService和BarService。咱们运用BarService 里边的办法进行调用FooService 中的办法。

            环境预备

            在进行业务演示之前,其实能够分为以下几种状况,依据排列组合,咱们能够得出以下八种状况

            • 调用者:有无业务
            • 调用者:是否有反常
            • 被调用者:有无业务**(这个是经过传达特点进行操控的)**所以并不在排列组合中
            • 被调用者:是否有反常

            反常类

            其间的RollbackException是咱们自己界说的一个反常类

            @Service

            public class BarServiceImpl implements BarService{

            @Autowired

            private FooService fooService;

            // PROPAGATION_REQUIRED演示 无业务

            @Override

            public void testRequiredNoTransactional() throws RollbackException {

            fooService.testRequiredTransactional();

            }

            }

            调用者

            在BarService中界说两个办法,一个是带着业务的,一个是不带业务的

            // 有业务
            @Override
            @Transactional(rollbackFor = Exception.class)
            public void hasTransactional() throws RollbackException {
            }
            // 无业务
            @Override
            public void noTransactional() throws RollbackException {

            }

            接下来咱们就依据俄上面界说的八种状况进行业务传达特点的学习。

            PROPAGATION_REQUIRED

            在此传达特点下,被调用方是否新建业务取决去调用者是否带着业务。

            想要了解这个传达特点的特性,其实咱们演示上面八种状况的两个比如就够了

            • 第一种状况咱们在被调用者抛出反常的状况下,假如查询不到刺进的数据,那么就阐明被调用者在调用者没有业务的状况下自己新建了业务。
            • 第二种状况咱们在调用者抛出反常的状况下,假如查询不到刺进的数据,那么就阐明被调用者在调用者有业务的状况下就参加当时业务了。

            咱们先来看一下被调用者的类的办法比如。

            @Service
            public class FooServiceImpl implements FooService {
            @Autowired
            private JdbcTemplate jdbcTemplate;

            // REQUIRED传达特点-被调用者有反常抛出
            @Override
            @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
            public void testRequiredHasException() throws RollbackException {
            jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ("+Global.REQUIRED_HAS_EXCEPTION+")");
            throw new RollbackException();
            }
            // REQUIRED传达特点-被调用者无反常抛出
            @Override
            @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
            public void testRequiredNoException() throws RollbackException {
            jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ("+Global.REQUIRED_NO_EXCEPTION+")");
            }
            }

            接下来咱们看一下调用者办法的比如

            @Service
            public class BarServiceImpl implements BarService{
            @Autowired
            private FooService fooService;
            // 有业务
            @Override
            @Transactional(rollbackFor = Exception.class)
            public void hasTransactional() throws RollbackException {
            // 调用者有业务,抛反常 被调用者无反常
            fooService.testRequiredNoException();
            throw new RollbackException();
            }
            // 无业务
            @Override
            public void noTransactional() throws RollbackException {
            // 调用者无业务,不抛反常 被调用者有反常
            fooService.testRequiredHasException();
            }
            }

            此刻咱们在程序调用时进行查询

            String noException = Global.REQUIRED_NO_EXCEPTION;
            String hasException = Global.REQUIRED_HAS_EXCEPTION;
            try {
            barService.noTransactional();
            }catch (Exception e){
            log.info("第一种状况 {}",
            jdbcTemplate
            .queryForObject("SELECT 钻石闪婚之溺宠小娇妻COUNT(*) FROM FOO WHERE BAR='"+hasException+"'", Long.class));
            }
            try {
            barService.hasTransactional();
            }catch (Exception e){
            log.info("第二种状况 {}",
            jdbcTemplate
            .queryForObject("SELECT COUNT(*) FROM FOO WHERE BAR='"+noException+"'", Long.class));
            }

            检查打印出来的日志

            2019-10-16 13:02:04.142 INFO 11869 --- [ main] c.e.t.t.TransactionApplication : 第一种状况 0
            2019-10-16 13:02:04.143 INFO 11869 --- [ main] c.e.t.t.TransactionApplication : 第二种状况 0

            咱们看到咱们都没有查到相应的数据,阐明数据都回滚了。此刻咱们应该就了解了那句话支撑当时业务,假如没有就新建业务

            PROPAGATION_SUPPORTS

            被调用者是否有业务,彻底依赖于调用者,调用者有业务则有业务,调用者没业务则没业务。

            接下来咱们仍是用上面的两个比如进行演示

            • 第一种状况:被调用者抛出反常的状况下,假如仍能查询到数据,阐明业务没有回滚,阐明被调用者没有业务
            • 第二种状况:调用者抛出反常状况下,假如查不到数据,阐明两个办法在一个业务中

            接下来仍然是比如演示

            被调用者,仅仅将@Transactional 注解中的propagation 特点替换为了Propagation.SUPPORTS

            // SUPPORTS传达特点-被调用者有反常抛出

            @Override

            @Transactional(rollbackFor = Exception.class,propagation = Propagation.SUPPORTS)

            public void testSupportsHasException() throws RollbackException {

            jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.SUPPORTS_HAS_EXCEPTION+"')");

            throw new RollbackException();

            }

            // SUPPORTS传达特点-被调用者无反常抛出

            @Override

            @Transactional(rollbackFor = ExSpring业务传达特点有那么难吗?看这一篇就够了ception.class,propagation = Propagation.SUPPORTS)

            public void testSupportsNoException() throws RollbackException {

            jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.SUPPORTS_NO_EXCEPTION+"')");

            }

            调用者和上面的比如调用相同,咱们直接检查履行作用

            2019-10-16 13:50:27.738 INFO 12174 --- [ main] c.e.t.t.TransactionApplication : 第一种状况 1
            2019-10-16 13:50:27.741 INFO 12174 --- [ main] c.e.t.t.TransactionApplication : 第二种状况 0

            咱们看到了在第一种状况下查到了数据,阐明在第一种状况下被调用者是没有业务的。此刻咱们应该就了解了这句话 支撑当时业务,假如没有就不以业务的办法运转

            PROPAGATION_MANDATORY

            仍然是这两个比如进行演示

            • 第一种状况:因为调用者没有业务,所以此传达特点下应该是抛反常的
            • 第二种状况:被调用者的业务和调用者业务是相同的

            接下来是被调用者的代码比如

            // MANDATORY传达特点-被调用者有反常抛出
            @Override
            @Transactional(rollbackFor = Exception.class,propagation = Propagation.MANDATORY)
            public void testMandatoryHasException() throws RollbackException {
            jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.SUPPORTS_HAS_EXCEPTION+"')");
            throw new RollbackException();
            }
            // MANDATORY传达特点-被调用者无反常抛出
            @Override
            @Transactional(rollbackFor = Exception.class,propagation = Propagation.MANDATORY)
            public void testMandatoryNoException() throws RollbackException {
            jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.SUPPORTS_NO_EXCEPTION+"')");
            }

            调用者和上面的比如调用相同,咱们直接检查履行作用

            2019-10-16 13:58:39.178 ERROR 12317 --- [ main] c.e.t.t.TransactionApplication : org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
            2019-10-16 13:58:39.276 INFO 12317 --- [ main] c.e.t.t.TransactionApplication : 第一种状况 0
            2019-10-16 13:58:39.281 INFO 12317 --- [ main] c.e.t.t.TransactionApplication : 第二种状况 0

            咱们发现和咱们估测相同,阐明被调用者是不会自己新建业务的,此刻咱们应该就了解了这句话支撑当时业务,假如当时没业务就抛反常

            PROPAGATION_REQUIRES_NEW

            此传达特点下,不管调用者是否有业务,被调用者都会新建一个业务

            • 第一种状况:调用者无业务,被调用者会新建业务,所以查不到数据
            • 第二种状况:调用者有业务,被调用者会新建一个业务,所以调用者抛反常影响不到被调用者,所以能查到数据

            接下来咱们演示代码。

            被调用者

            // REQUIRES_NEW传达特点-被调用者有反常抛出

            @Override

            @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)

            public void testRequiresNewHasException() throws RollbackException {

            jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.REQUIRES_NEW_HAS_EXCEPTION+"')");

            throw new RollbackException();

            }

            // REQUIRES_NEW传达特点-被调用者无反常抛出

            @Override

            @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)

            public void testRequiresNewNoException() throws RollbackException {

            jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.REQUIRES_NEW_NO_EXCEPTION+"')");

            }

            调用者的比如和上面的相同,咱们直接来看履行状况

            2019-10-16 16:29:20.296 INFO 15553 --- [ main] c.e.t.t.TransactionApplication : 第一种状况 0
            2019-10-16 16:29:20.298 INFO 15553 --- [ main] c.e.t.t.TransactionApplication : 第二种状况 1

            咱们发现和咱们的推论是相同的,阐明调用者的业务和被调用者的业务彻底无关。此刻咱们应该就了解这句话了不管当时是否有业务,都会新起一个业务

            PROPAGATION_NOT_SUPPORTED

            不管调用者是否有业务,被调用者都Spring业务传达特点有那么难吗?看这一篇就够了不以业务的办法运转

            相同是这两个比如

            • 第一种状况:被调用者都不会有业务,那么在抛反常之后就能查到相应的数据
            • 第二种状况:在调用者有业务的状况下,被调用者也会在无业务环境下运转,所以咱们仍然能查到数据

            接下来验证咱们的猜想

            // NOT_SUPPORTED传达特点-被调用者有反常抛出

            @Override

            @Transactional(rollbackFor = Exception.class,propagation = Propagation.NOT_SUPPORTED)

            public void testNotSupportHasException() throws RollbackException {

            jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+GlobSpring业务传达特点有那么难吗?看这一篇就够了al.NOT_SUPPORTS_HAS_EXCEPTION+"')");

            throw new RollbackException();

            }

            // NOT_SUPPORTED传达特点-被调用者无反常抛出

            @Override

            @Transactional(rollbackFor = Exception.class,propagation = Propagation.NOT_SUPPORTED)

            public void testNotSupportNoException() throws RollbackException {

            Spring业务传达特点有那么难吗?看这一篇就够了jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.NOT_SUPPORTS_NO_EXCEPTION+"')");

            }

            然后检查履行成果

            2019-10-16 16:38:35.065 INFO 15739 --- [ main] c.e.t.t.TransactionApplication : 第一种状况 1
            2019-10-16 16:38:35.067 INFO 15739 --- [ main] c.e.t.t.TransactionApplication : 第二种状况 1

            咱们能够看到在最终两种状况都查到了数据,依据演示作用应该能够了解这句话了,不支撑业务,假如当时存在业务,就将此业务挂起不以业务办法运转

            PROPAGATION_NEVER

            调用者有业务,被调用者就会抛出反常

            这个就不演示,信任咱们看到这儿应该都会理解在第一种状况下咱们是能够查到数据的。在第二种状况下因为调用者带着业务,所以会抛反常。

            PROPAGATION_NESTED

            此传达特点下,被调用者的业务是调用者的业务的子集。

            咱们要点说一下NESTED的传达特点的特性

            关于什么是嵌套业务的联系,咱们用下面三个比如能够进行演示。

            • 第一种状况:假如查不到数据,则阐明在调用者无业务状况下,被调用者会新起一个业务
            • 第二种状况:假如查不到数据,阐明外层业务能够影响内层业务
            • 第三种状况:假如查到数据,阐明内层业务不影响外层业务

            接下来咱们编写详细的代码

            // NESTED传达特点-回滚业务
            @Override
            @Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)
            public void testNestedHasException() throws RollbackException {
            jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.NESTED_HAS_EXCEPTION+"')");
            // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new RollbackException();
            }
            // NESTED传达特点-不回滚业务
            @Override
            @Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)
            public void testNestedNoException() throws RollbackException {
            jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.NESTED_NO_EXCEPTION+"')");
            }

            然后接下来的调用者也会有点差异

            @Override
            @Transactional()
            public void hasTransactionalNoException() throws RollbackException {
            // NESTED传达特点 - 调用者有业务,不抛反常 被调用者有反常
            jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.NESTED_HAS_EXCEPTION_TWO+"')");
            fooService.testNestedHasException();
            }

            然后履行作用

            2019-10-16 18:01:06.387 INFO 17172 --- [ main] c.e.t.t.TransactionApplication : 第一种状况 0
            2019-10-16 18:01:06.389 INFO 17172 --- [ main] c.e.t.t.TransactionApplication : 第二种状况 0
            2019-10-16 18:01:06.390 INFO 17172 --- [ main] c.e.t.t.TransactionApplication : 第三种状况 1

            能够看出来嵌套业务的实质便是外层会影响内层,内层不影响外层。而REQUIRES_NEW则是互不影响

            总结

            到现在咱们现已悉数剖析完了七种传达特点,从写这篇文章开端到完毕其间也碰到过一些坑,有些是不自己实践一遍是底子不知道的,所以我仍是主张读者看完这篇文章今后自己进行实践,演示各种状况,只要这样才能够纯熟于心。

            请关注微信公众号
            微信二维码
            不容错过
            Powered By Z-BlogPHP