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 > _________________________________________ 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]

