You can annotate a method with @Transactional(propagation=REQUIRES_NEW). I don't know whether this is supported on all databases, or whether there are any other pitfalls in practice.
-Darius On Mon, Feb 27, 2012 at 8:45 AM, Burke Mamlin <[email protected]>wrote: > Can we devise a convention/recipe for cleanly creating a separate writable > transaction within a read-only transaction? If someone wants/needs to > create some side effects inside a read-only transaction, it would be nice > to have a common convention for how to implement such a side effect (e.g., > either appropriate annotations and/or a utility method). > > For example, a service provides a transactionless or read-only transaction > around a method and some process introduced by a module during that method > wants to write something to the database on the side. Is there a way for > the module to create it's own separate transaction to perform the side > effect without forcing the service method to create a transaction? > > -Burke > > > On Mon, Feb 27, 2012 at 9:59 AM, Ben Wolfe <[email protected]> wrote: > >> @Transactional(readOnly=true, propagation=Propagation.SUPPORTS) looks >> like the best solution. >> >> Dissecting that suggestion according to the article: >> >> *@Transactional* so that hibernate is happen and has its endpoints >> *readOnly=true* so that a database write doesn't occur >> *Propogation.SUPPORTS* so that the transaction is never really started >> unless asked for >> >> Did you confirm this still works with hibernate? (validating my first >> assumption above about @Transactional?) >> >> All read/write methods will need >> @Transaction(propogration=Propogration.REQUIRED) >> >> Ben >> >> >> On Sun, Feb 26, 2012 at 7:22 AM, Rafal Korytkowski <[email protected]>wrote: >> >>> I'd vote to put @Transactional(readOnly=true, >>> propagation=Propagation.SUPPORTS) at the class level of service layer impls >>> and fine tune methods that aren't read only. >>> >>> Propagation.SUPPORTS allows to eliminate the transaction overhead that >>> Darius is hoping to achieve with the DAO example in a more general and >>> nicer way. More info here [0]. >>> >>> There's not much difference between having transactional DAOs and >>> Services. The latter is more widely used for the reason I gave, but it's a >>> matter of taste. >>> >>> -Rafal >>> >>> [0] - http://www.ibm.com/developerworks/java/library/j-ts1/index.html >>> >>> >>> On 24 February 2012 22:00, Darius Jazayeri <[email protected]>wrote: >>> >>>> Spring tries to use the existing transaction unless you say >>>> @Transactional(propagation=Propagation.REQUIRES_NEW). >>>> >>>> I would *love* to get rid of the @Transactional annotations on our >>>> services, and just put annotations on the methods that actually require >>>> them. >>>> >>>> -Darius >>>> >>>> >>>> On Fri, Feb 24, 2012 at 12:32 PM, Ben Wolfe <[email protected]> wrote: >>>> >>>>> FYI, here is the relevant ticket: >>>>> https://tickets.openmrs.org/browse/TRUNK-208 >>>>> >>>>> I could live with it on the DAO if we also examine all serviceimpls >>>>> for multiple calls to the DAO layer and add the annotation to the impl if >>>>> it does more than one. >>>>> >>>>> Can we do away with the generic @Transactional on the class and force >>>>> devs to add @Transactional on methods that need it? This should remove >>>>> the >>>>> need for @Transactional(readOnly=true) and limit the number of times its >>>>> forgotten. Alternatively, we make the class level annotation >>>>> readOnly=true. >>>>> >>>>> Are we also sure that if a transaction is started at the service layer >>>>> that the DAO layer is using that same one instead of starting a new one? >>>>> >>>>> Ben >>>>> >>>>> >>>>> On Fri, Feb 24, 2012 at 3:13 PM, Darius Jazayeri < >>>>> [email protected]> wrote: >>>>> >>>>>> The reason I'd rather have them in the HibernateDAO is so we can >>>>>> write a service method like this, without paying the transactional >>>>>> penalty: >>>>>> >>>>>> public MySettings getSettings() { >>>>>> if (cached == null) { >>>>>> cached = dao.getSettings(); // this method has an >>>>>> @Transactional annotation >>>>>> } >>>>>> return cached; >>>>>> } >>>>>> >>>>>> Basically I'm saying that the transactional annotation should be put >>>>>> in the concrete DAO only where we actually hit a transactional datastore. >>>>>> >>>>>> If we're putting the annotations in the ServiceImpl I'd need to do >>>>>> something like this: >>>>>> >>>>>> public MySettings getSettings() { >>>>>> if (cached == null) { >>>>>> cached = getSettingsFromDao(); >>>>>> } >>>>>> return cached; >>>>>> } >>>>>> >>>>>> @Transactional(readOnly=true) >>>>>> private MySettings getSettingsFromDao() { >>>>>> return dao.getSettings(); >>>>>> } >>>>>> >>>>>> It's not the end of the world to have to do that, but is there any >>>>>> theoretical justification or best-practice recommendation that says we >>>>>> should put annotations in the service layer when we believe that we're >>>>>> calling a transactional DAO, rather than in the DAO layer when we know >>>>>> for >>>>>> sure we're hitting the datastore? >>>>>> >>>>>> -Darius >>>>>> >>>>>> PS- Definitely if a ServiceImpl or a Controller method is going to >>>>>> make multiple Service or DAO calls, it should explicitly mark the >>>>>> transaction itself. But that's independent. >>>>>> >>>>>> >>>>>> On Fri, Feb 24, 2012 at 10:08 AM, Ben Wolfe <[email protected]> wrote: >>>>>> >>>>>>> Yes, lets move these to the ServiceImpl. Do we have a ticket >>>>>>> somewhere to move the rest of our transaction annotations from >>>>>>> interface to >>>>>>> impl? >>>>>>> >>>>>>> Ben >>>>>>> >>>>>>> >>>>>>> On Fri, Feb 24, 2012 at 9:55 AM, Wyclif Luyima >>>>>>> <[email protected]>wrote: >>>>>>> >>>>>>>> @Rafal, i agree with what you are saying, so we should move them >>>>>>>> from HibernateVisitDao to VisitServiceImpl? >>>>>>>> >>>>>>>> Wyclif >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> On Fri, Feb 24, 2012 at 5:15 AM, Rafal Korytkowski < >>>>>>>> [email protected]> wrote: >>>>>>>> >>>>>>>>> I've found a way to have the advice around @Transactional so we >>>>>>>>> don't need to change anything in Visits. >>>>>>>>> >>>>>>>>> Anyway, I don't think we should move @Transactional to the DAO >>>>>>>>> layer. In general it's the service layer that defines units of work >>>>>>>>> that >>>>>>>>> should be transactional. If you have multiple calls to DAO in a >>>>>>>>> service >>>>>>>>> method, you will want to have @Transactional in the service method >>>>>>>>> anyway. >>>>>>>>> >>>>>>>>> -Rafal >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> On 24 February 2012 03:11, Darius Jazayeri <[email protected]>wrote: >>>>>>>>> >>>>>>>>>> Moving this to the dev list. >>>>>>>>>> >>>>>>>>>> Wyclif, I assume that you mean from HibernateVisitDAO to >>>>>>>>>> VisitServiceImpl... >>>>>>>>>> >>>>>>>>>> So, in the long run, we need to move the transactional >>>>>>>>>> annotations off of the service interface. I'd argue that they should >>>>>>>>>> go to >>>>>>>>>> the concrete DAO, and only on the methods that actually hit the >>>>>>>>>> database. >>>>>>>>>> The alternative would be to move them to the ServiceImpl. >>>>>>>>>> >>>>>>>>>> That said, I'm fine if we want to move them from >>>>>>>>>> HibernateVisitDAO up to the VisitService *interface* for >>>>>>>>>> consistency, so that we can refactor *all* our services later. >>>>>>>>>> But what's the argument for moving it from the HibernateDAO to the >>>>>>>>>> ServiceImpl? >>>>>>>>>> >>>>>>>>>> Ideally Rafal will quickly figure out how to move the recent >>>>>>>>>> advice code he wrote so it's triggered by any @Transactional method >>>>>>>>>> anywhere, and this will be moot. >>>>>>>>>> >>>>>>>>>> -Darius >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On Thu, Feb 23, 2012 at 5:58 PM, Wyclif Luyima < >>>>>>>>>> [email protected]> wrote: >>>>>>>>>> >>>>>>>>>>> Hi guys, >>>>>>>>>>> >>>>>>>>>>> @Daniel, we need to move the @Transanctional annotations from >>>>>>>>>>> HibernateVisitDao to ConceptServiceImpl before cutting the 1.9 RC >>>>>>>>>>> >>>>>>>>>>> Wyclif >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>> ------------------------------ >>>>>>>>>> Click here to >>>>>>>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from >>>>>>>>>> OpenMRS Developers' mailing list >>>>>>>>> >>>>>>>>> >>>>>>>>> ------------------------------ >>>>>>>>> Click here to >>>>>>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from >>>>>>>>> OpenMRS Developers' mailing list >>>>>>>>> >>>>>>>> >>>>>>>> ------------------------------ >>>>>>>> Click here to >>>>>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from >>>>>>>> OpenMRS Developers' mailing list >>>>>>>> >>>>>>> >>>>>>> ------------------------------ >>>>>>> Click here to >>>>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from >>>>>>> OpenMRS Developers' mailing list >>>>>>> >>>>>> >>>>>> ------------------------------ >>>>>> Click here to >>>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from >>>>>> OpenMRS Developers' mailing list >>>>>> >>>>> >>>>> ------------------------------ >>>>> Click here to >>>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from >>>>> OpenMRS Developers' mailing list >>>>> >>>> >>>> ------------------------------ >>>> Click here to >>>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from >>>> OpenMRS Developers' mailing list >>>> >>> >>> ------------------------------ >>> Click here to >>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from >>> OpenMRS Developers' mailing list >>> >> >> ------------------------------ >> Click here to >> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from >> OpenMRS Developers' mailing list >> > > ------------------------------ > Click here to > unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from > OpenMRS Developers' mailing list > _________________________________________ To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to [email protected] with "SIGNOFF openmrs-devel-l" in the body (not the subject) of your e-mail. [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]

