Ek Açıklama @Transactional. Nasıl geri alınır?


91

Bu notu bir Dao sınıfı için başarıyla kullandım. Ve geri alma, testler için çalışır.

Ama şimdi sadece testleri değil, gerçek kodu da geri almam gerekiyor. Testlerde kullanılmak üzere özel açıklamalar vardır. Ancak test dışı kod için hangi ek açıklamalar var? Bu benim için büyük bir soru. Zaten bunun için bir gün geçirdim. Resmi belgeler ihtiyaçlarımı karşılamadı.

class MyClass { // this does not make rollback! And record appears in DB.
        EmployeeDaoInterface employeeDao;

        public MyClass() {
            ApplicationContext context = new ClassPathXmlApplicationContext(
                    new String[] { "HibernateDaoBeans.xml" });
            employeeDao = (IEmployeeDao) context.getBean("employeeDao");
         }

        @Transactional(rollbackFor={Exception.class})
    public void doInsert( Employee newEmp ) throws Exception {
        employeeDao.insertEmployee(newEmp);
        throw new RuntimeException();
    }
}

çalışan Dao

@Transactional
public class EmployeeDao implements IEmployeeDao {
    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public void insertEmployee(Employee emp) {
        sessionFactory.getCurrentSession().save(emp);
    }
}

Ve işte ek açıklamaların iyi çalıştığı bir test:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/HibernateDaoBeans.xml" })
@TransactionConfiguration(transactionManager = "txManager", defaultRollback = true)
@Transactional
public class EmployeeDaoTest {

    @Autowired
    EmployeeDaoInterface empDao;

    @Test
    public void insert_record() {
       ...
       assertTrue(empDao.insertEmployee(newEmp));
    }

Hazırda bekletme incelemeleri

   ...
<bean id="employeeDao" class="Hibernate.EmployeeDao">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
    <tx:annotation-driven transaction-manager="txManager"/>

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
   ...



** EVET, işlemi geri aldım. Servis için BEAN'i ekledim ... ve ardından @Transactional ek açıklama çalışmaya başlar :-) **

<bean id="service" class="main.MyClass">
    <property name="employeeDao" ref="employeeDao" />
</bean>

Hepinize teşekkürler, Rusya sizi unutmayacak!

Yanıtlar:


163

Sadece RuntimeExceptionolarak işaretlenmiş bir yöntemden herhangi birini atın @Transactional.

Varsayılan olarak tüm RuntimeExceptions geri alma işlemi, kontrol edilen istisnalar değil. Bu bir EJB mirasıdır. Bunu rollbackFor()ve noRollbackFor()ek açıklama parametrelerini kullanarak yapılandırabilirsiniz :

@Transactional(rollbackFor=Exception.class)

Bu, herhangi bir istisna atıldıktan sonra işlemi geri alır .


1
Denedim. İşe yaramıyor! Doğrudan Dao nesnesinde değil, işe yarayabilecek Geri Alma işleminden bahsediyorum. @Transactional kullanan Dao methoda çağrı sırasını kullanan başka bir nesneden bahsediyorum. Ve bu Tao olarak adlandırılan sınıfım için aynı notu eklemeye çalışıyorum. Ama burada çalışmıyor.
Moskova Çocuğu

5
Gerçekten bu şekilde çalışıyor :-). Birkaç DAO'yu arayan bir hizmetiniz varsa, hizmetin de bir @Transactionalek açıklamaya sahip olması gerekir . Aksi takdirde, her DAO çağrısı siz hizmette bir istisna atmadan önce yeni işlemi başlatır ve taahhüt eder. Sonuç olarak: istisna, olarak işaretlenmiş bir yöntem bırakmalıdır (kaçmalıdır) @Transactional.
Tomasz Nurkiewicz

İlk gönderide eklenen koda bakın. Sahip olduğum kodun bir parçası var. Ve yürütmeden sonra kayıt DB'de var. => geri alma henüz çalışmıyor.
Moskova Çocuğu

DAO'dan bir istisna atmak işlemi de geri almıyor mu? Eğer var mı org.springframework.orm.hibernate3.HibernateTransactionManagersenin Bahar bağlamda yapılandırılan? org.springframework.transactionLogger'ı etkinleştirirseniz , ilginç bir şey gösterir mi?
Tomasz Nurkiewicz

1
Spring Boot kullanıyorsanız ve DataSource'u otomatik olarak yapılandırmasına izin verirseniz, auto-commit'in varsayılan olarak true olarak ayarlandığı HikariDataSource'u kullanır. Bunu false olarak ayarlamanız gerekir: hikariDataSource.setAutoCommit (false); DataSourceTransactionManager bean'i yapılandırırken @Configuration sınıfında bu değişikliği yaptım.
Alex

83

veya programatik olarak

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

12
Evet. Çünkü bazen bir hata yapmadan geri dönmeniz gerekir.
Erica Kane

2
Sen bir hayat kurtarıcısın.
Walls

Bu, bir geri alma imosunu çağırmanın daha uygun bir yoludur, ideal olarak bilinen veya kontrol edilen koşullar için istisnalar atmak istemezsiniz.
jalpino

2
Bazen işe yaramıyor. Örneğin, benim durumumda bir işlem hizmetim ve işlemsel olmayan depom var. Depoyu servisten arıyorum, bu yüzden servis tarafından açılan bir işleme katılması gerekiyor. Ancak kodunuzu işlemsel olmayan depomdan çağırırsam, işlemin var olmasına rağmen NoTransactionException atıyor.
Victor Dombrovsky

3
"İşlemsel olmayan deponuzda" hangi işlemi geri almak istiyorsunuz?
Stefan K.

5

Geri almak istediğiniz yöntemden kontrol edilmemiş bir istisna atabilirsiniz. Bu, bahar tarafından algılanacak ve işleminiz yalnızca geri alma olarak işaretlenecektir.

Burada Spring kullandığınızı varsayıyorum. Ve testlerinizde bahsettiğiniz notların bahar testine dayalı açıklamalar olduğunu varsayıyorum.

Spring Framework işlem altyapısına bir işlemin çalışmasının geri alınacağını belirtmenin önerilen yolu, şu anda bir işlem bağlamında yürütülen koddan bir İstisna atmaktır.

ve şunlara dikkat edin:

Spring Framework'ün işlem altyapısı kodunun, varsayılan olarak, yalnızca çalışma zamanı, denetlenmemiş istisnalar durumunda geri alma için bir işlemi işaretleyeceğini lütfen unutmayın; diğer bir deyişle, atılan istisna bir RuntimeException örneği veya alt sınıfı olduğunda.


1

Benim için geri alma yeterli değildi, bu yüzden bunu koymak zorunda kaldım ve beklendiği gibi çalışıyor:

@Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)

Umut ediyorum bu yardım eder :-)


1
hayır bu hiç yardımcı olmuyor TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();altınızda yardımcı
Enerccio
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.